|
1 /* |
|
2 |
|
3 Copyright (C) 2000,2002,2004,2005,2006 Silicon Graphics, Inc. All Rights Reserved. |
|
4 Portions Copyright (C) 2007 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 /* The address of the Free Software Foundation is |
|
37 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, |
|
38 Boston, MA 02110-1301, USA. |
|
39 SGI has moved from the Crittenden Lane address. |
|
40 */ |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 #include "config.h" |
|
47 #include "dwarf_incl.h" |
|
48 #include <stdio.h> |
|
49 #include <stdlib.h> |
|
50 #include "dwarf_frame.h" |
|
51 #include "dwarf_arange.h" /* Using Arange as a way to build a |
|
52 list */ |
|
53 |
|
54 #define FDE_NULL_CHECKS_AND_SET_DBG(fde,dbg ) \ |
|
55 do { \ |
|
56 if ((fde) == NULL) { \ |
|
57 _dwarf_error(NULL, error, DW_DLE_FDE_NULL); \ |
|
58 return (DW_DLV_ERROR); \ |
|
59 } \ |
|
60 (dbg)= (fde)->fd_dbg; \ |
|
61 if ((dbg) == NULL) { \ |
|
62 _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL);\ |
|
63 return (DW_DLV_ERROR); \ |
|
64 } } while (0) |
|
65 |
|
66 |
|
67 #define MIN(a,b) (((a) < (b))? a:b) |
|
68 |
|
69 static void _dwarf_init_regrule_table(struct Dwarf_Reg_Rule_s *t1reg, |
|
70 int last_reg_num, |
|
71 int initial_value); |
|
72 static int dwarf_initialize_fde_table(Dwarf_Debug dbg, |
|
73 struct Dwarf_Frame_s *fde_table, |
|
74 unsigned table_real_data_size, |
|
75 Dwarf_Error * error); |
|
76 static void dwarf_free_fde_table(struct Dwarf_Frame_s *fde_table); |
|
77 |
|
78 #if 0 |
|
79 /* Only used for debugging libdwarf. */ |
|
80 static void dump_frame_rule(char *msg, |
|
81 struct Dwarf_Reg_Rule_s *reg_rule); |
|
82 #endif |
|
83 |
|
84 |
|
85 |
|
86 /* |
|
87 This function is the heart of the debug_frame stuff. Don't even |
|
88 think of reading this without reading both the Libdwarf and |
|
89 consumer API carefully first. This function basically executes |
|
90 frame instructions contained in a Cie or an Fde, but does in a |
|
91 number of different ways depending on the information sought. |
|
92 Start_instr_ptr points to the first byte of the frame instruction |
|
93 stream, and final_instr_ptr to the to the first byte after the |
|
94 last. |
|
95 |
|
96 The offsets returned in the frame instructions are factored. That |
|
97 is they need to be multiplied by either the code_alignment_factor |
|
98 or the data_alignment_factor, as appropriate to obtain the actual |
|
99 offset. This makes it possible to expand an instruction stream |
|
100 without the corresponding Cie. However, when an Fde frame instr |
|
101 sequence is being expanded there must be a valid Cie with a pointer |
|
102 to an initial table row. |
|
103 |
|
104 |
|
105 If successful, returns DW_DLV_OK |
|
106 And sets returned_count thru the pointer |
|
107 if make_instr is true. |
|
108 If make_instr is false returned_count |
|
109 should NOT be used by the caller (returned_count |
|
110 is set to 0 thru the pointer by this routine...) |
|
111 If unsuccessful, returns DW_DLV_ERROR |
|
112 and sets returned_error to the error code |
|
113 |
|
114 It does not do a whole lot of input validation being a private |
|
115 function. Please make sure inputs are valid. |
|
116 |
|
117 (1) If make_instr is true, it makes a list of pointers to |
|
118 Dwarf_Frame_Op structures containing the frame instructions |
|
119 executed. A pointer to this list is returned in ret_frame_instr. |
|
120 Make_instr is true only when a list of frame instructions is to be |
|
121 returned. In this case since we are not interested in the contents |
|
122 of the table, the input Cie can be NULL. This is the only case |
|
123 where the inpute Cie can be NULL. |
|
124 |
|
125 (2) If search_pc is true, frame instructions are executed till |
|
126 either a location is reached that is greater than the search_pc_val |
|
127 provided, or all instructions are executed. At this point the |
|
128 last row of the table generated is returned in a structure. |
|
129 A pointer to this structure is supplied in table. |
|
130 |
|
131 (3) This function is also used to create the initial table row |
|
132 defined by a Cie. In this case, the Dwarf_Cie pointer cie, is |
|
133 NULL. For an FDE, however, cie points to the associated Cie. |
|
134 |
|
135 make_instr - make list of frame instr? 0/1 |
|
136 ret_frame_instr - Ptr to list of ptrs to frame instrs |
|
137 search_pc - Search for a pc value? 0/1 |
|
138 search_pc_val - Search for this pc value |
|
139 initial_loc - Initial code location value. |
|
140 start_instr_ptr - Ptr to start of frame instrs. |
|
141 final_instr_ptr - Ptr just past frame instrs. |
|
142 table - Ptr to struct with last row. |
|
143 cie - Ptr to Cie used by the Fde. |
|
144 |
|
145 */ |
|
146 |
|
147 int |
|
148 _dwarf_exec_frame_instr(Dwarf_Bool make_instr, |
|
149 Dwarf_Frame_Op ** ret_frame_instr, |
|
150 Dwarf_Bool search_pc, |
|
151 Dwarf_Addr search_pc_val, |
|
152 Dwarf_Addr initial_loc, |
|
153 Dwarf_Small * start_instr_ptr, |
|
154 Dwarf_Small * final_instr_ptr, |
|
155 Dwarf_Frame table, |
|
156 Dwarf_Cie cie, |
|
157 Dwarf_Debug dbg, |
|
158 Dwarf_Half reg_num_of_cfa, |
|
159 Dwarf_Sword * returned_count, |
|
160 int *returned_error) |
|
161 { |
|
162 #define ERROR_IF_REG_NUM_TOO_HIGH(macreg,machigh_reg) \ |
|
163 do { \ |
|
164 if ((macreg) >= (machigh_reg) || (macreg) < 0) { \ |
|
165 SIMPLE_ERROR_RETURN(DW_DLE_DF_REG_NUM_TOO_HIGH); \ |
|
166 } \ |
|
167 } /*CONSTCOND */ while(0) |
|
168 #define SIMPLE_ERROR_RETURN(code) \ |
|
169 free(localregtab); \ |
|
170 *returned_error = code; \ |
|
171 return DW_DLV_ERROR |
|
172 |
|
173 /* Sweeps the frame instructions. */ |
|
174 Dwarf_Small *instr_ptr; |
|
175 |
|
176 /* Register numbers not limited to just 255, thus not using |
|
177 Dwarf_Small. */ |
|
178 typedef int reg_num_type; |
|
179 |
|
180 Dwarf_Unsigned factored_N_value; |
|
181 Dwarf_Signed signed_factored_N_value; |
|
182 Dwarf_Addr current_loc = initial_loc; /* code location/ |
|
183 pc-value |
|
184 corresponding to the |
|
185 frame instructions. |
|
186 Starts at zero when |
|
187 the caller has no |
|
188 value to pass in. */ |
|
189 |
|
190 /* Must be min de_pointer_size bytes and must be at least sizeof |
|
191 Dwarf_ufixed */ |
|
192 Dwarf_Unsigned adv_loc; |
|
193 |
|
194 int reg_count = dbg->de_frame_reg_rules_entry_count; |
|
195 struct Dwarf_Reg_Rule_s *localregtab = calloc(reg_count, |
|
196 sizeof(struct |
|
197 Dwarf_Reg_Rule_s)); |
|
198 |
|
199 struct Dwarf_Reg_Rule_s cfa_reg; |
|
200 |
|
201 |
|
202 /* This is used to end executing frame instructions. */ |
|
203 /* Becomes true when search_pc is true and current_loc */ |
|
204 /* is greater than search_pc_val. */ |
|
205 Dwarf_Bool search_over = false; |
|
206 |
|
207 /* Used by the DW_FRAME_advance_loc instr */ |
|
208 /* to hold the increment in pc value. */ |
|
209 Dwarf_Addr adv_pc; |
|
210 |
|
211 /* Contains the length in bytes of */ |
|
212 /* an leb128 encoded number. */ |
|
213 Dwarf_Word leb128_length; |
|
214 |
|
215 /* Counts the number of frame instructions executed. */ |
|
216 Dwarf_Word instr_count = 0; |
|
217 |
|
218 /* |
|
219 These contain the current fields of the current frame |
|
220 instruction. */ |
|
221 Dwarf_Small fp_base_op = 0; |
|
222 Dwarf_Small fp_extended_op; |
|
223 reg_num_type fp_register; |
|
224 |
|
225 /* The value in fp_offset may be signed, though we call it |
|
226 unsigned. This works ok for 2-s complement arithmetic. */ |
|
227 Dwarf_Unsigned fp_offset; |
|
228 Dwarf_Off fp_instr_offset; |
|
229 |
|
230 /* |
|
231 Stack_table points to the row (Dwarf_Frame ie) being pushed or |
|
232 popped by a remember or restore instruction. Top_stack points to |
|
233 the top of the stack of rows. */ |
|
234 Dwarf_Frame stack_table; |
|
235 Dwarf_Frame top_stack = NULL; |
|
236 |
|
237 /* |
|
238 These are used only when make_instr is true. Curr_instr is a |
|
239 pointer to the current frame instruction executed. |
|
240 Curr_instr_ptr, head_instr_list, and curr_instr_list are used to |
|
241 form a chain of Dwarf_Frame_Op structs. Dealloc_instr_ptr is |
|
242 used to deallocate the structs used to form the chain. |
|
243 Head_instr_block points to a contiguous list of pointers to the |
|
244 Dwarf_Frame_Op structs executed. */ |
|
245 Dwarf_Frame_Op *curr_instr; |
|
246 Dwarf_Chain curr_instr_item, dealloc_instr_item; |
|
247 Dwarf_Chain head_instr_chain = NULL; |
|
248 Dwarf_Chain tail_instr_chain = NULL; |
|
249 Dwarf_Frame_Op *head_instr_block; |
|
250 |
|
251 /* |
|
252 These are the alignment_factors taken from the Cie provided. |
|
253 When no input Cie is provided they are set to 1, because only |
|
254 factored offsets are required. */ |
|
255 Dwarf_Sword code_alignment_factor = 1; |
|
256 Dwarf_Sword data_alignment_factor = 1; |
|
257 |
|
258 /* |
|
259 This flag indicates when an actual alignment factor is needed. |
|
260 So if a frame instruction that computes an offset using an |
|
261 alignment factor is encountered when this flag is set, an error |
|
262 is returned because the Cie did not have a valid augmentation. */ |
|
263 Dwarf_Bool need_augmentation = false; |
|
264 |
|
265 Dwarf_Word i; |
|
266 |
|
267 /* Initialize first row from associated Cie. Using temp regs |
|
268 explicity */ |
|
269 |
|
270 |
|
271 if (localregtab == 0) { |
|
272 SIMPLE_ERROR_RETURN(DW_DLE_ALLOC_FAIL); |
|
273 } |
|
274 { |
|
275 struct Dwarf_Reg_Rule_s *t1reg = localregtab; |
|
276 struct Dwarf_Reg_Rule_s *t1end = t1reg + reg_count; |
|
277 |
|
278 if (cie != NULL && cie->ci_initial_table != NULL) { |
|
279 struct Dwarf_Reg_Rule_s *t2reg = |
|
280 cie->ci_initial_table->fr_reg; |
|
281 |
|
282 if (reg_count != cie->ci_initial_table->fr_reg_count) { |
|
283 /* Should never happen, it makes no sense to have the |
|
284 table sizes change. There is no real allowance for |
|
285 the set of registers to change dynamically in a |
|
286 single Dwarf_Debug (except the size can be set near |
|
287 initial Dwarf_Debug creation time). */ |
|
288 SIMPLE_ERROR_RETURN |
|
289 (DW_DLE_FRAME_REGISTER_COUNT_MISMATCH); |
|
290 } |
|
291 |
|
292 for (; t1reg < t1end; t1reg++, t2reg++) { |
|
293 *t1reg = *t2reg; |
|
294 } |
|
295 cfa_reg = cie->ci_initial_table->fr_cfa_rule; |
|
296 } else { |
|
297 _dwarf_init_regrule_table(t1reg, |
|
298 reg_count, |
|
299 dbg->de_frame_rule_initial_value); |
|
300 _dwarf_init_regrule_table(&cfa_reg, 1, |
|
301 dbg->de_frame_rule_initial_value); |
|
302 } |
|
303 } |
|
304 |
|
305 /* |
|
306 The idea here is that the code_alignment_factor and |
|
307 data_alignment_factor which are needed for certain instructions |
|
308 are valid only when the Cie has a proper augmentation string. So |
|
309 if the augmentation is not right, only Frame instruction can be |
|
310 read. */ |
|
311 if (cie != NULL && cie->ci_augmentation != NULL) { |
|
312 code_alignment_factor = cie->ci_code_alignment_factor; |
|
313 data_alignment_factor = cie->ci_data_alignment_factor; |
|
314 } else { |
|
315 need_augmentation = !make_instr; |
|
316 } |
|
317 |
|
318 instr_ptr = start_instr_ptr; |
|
319 while ((instr_ptr < final_instr_ptr) && (!search_over)) { |
|
320 Dwarf_Small instr = 0; |
|
321 Dwarf_Small opcode = 0; |
|
322 reg_num_type reg_no = 0; |
|
323 |
|
324 |
|
325 fp_instr_offset = instr_ptr - start_instr_ptr; |
|
326 instr = *(Dwarf_Small *) instr_ptr; |
|
327 instr_ptr += sizeof(Dwarf_Small); |
|
328 |
|
329 fp_base_op = (instr & 0xc0) >> 6; |
|
330 if ((instr & 0xc0) == 0x00) { |
|
331 opcode = instr; /* is really extended op */ |
|
332 fp_extended_op = (instr & (~(0xc0))) & 0xff; |
|
333 } else { |
|
334 opcode = instr & 0xc0; /* is base op */ |
|
335 fp_extended_op = 0; |
|
336 } |
|
337 |
|
338 fp_register = 0; |
|
339 fp_offset = 0; |
|
340 switch (opcode) { |
|
341 case DW_CFA_advance_loc: |
|
342 { |
|
343 /* base op */ |
|
344 fp_offset = adv_pc = instr & DW_FRAME_INSTR_OFFSET_MASK; |
|
345 |
|
346 if (need_augmentation) { |
|
347 SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); |
|
348 } |
|
349 adv_pc = adv_pc * code_alignment_factor; |
|
350 |
|
351 search_over = search_pc && |
|
352 (current_loc + adv_pc > search_pc_val); |
|
353 /* If gone past pc needed, retain old pc. */ |
|
354 if (!search_over) |
|
355 current_loc = current_loc + adv_pc; |
|
356 break; |
|
357 } |
|
358 |
|
359 case DW_CFA_offset: |
|
360 { /* base op */ |
|
361 reg_no = |
|
362 (reg_num_type) (instr & DW_FRAME_INSTR_OFFSET_MASK); |
|
363 ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); |
|
364 |
|
365 factored_N_value = |
|
366 _dwarf_decode_u_leb128(instr_ptr, &leb128_length); |
|
367 instr_ptr = instr_ptr + leb128_length; |
|
368 |
|
369 fp_register = reg_no; |
|
370 fp_offset = factored_N_value; |
|
371 |
|
372 if (need_augmentation) { |
|
373 SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); |
|
374 } |
|
375 |
|
376 localregtab[reg_no].ru_is_off = 1; |
|
377 localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET; |
|
378 localregtab[reg_no].ru_register = reg_num_of_cfa; |
|
379 localregtab[reg_no].ru_offset_or_block_len = |
|
380 factored_N_value * data_alignment_factor; |
|
381 |
|
382 break; |
|
383 } |
|
384 |
|
385 case DW_CFA_restore: |
|
386 { /* base op */ |
|
387 reg_no = (instr & DW_FRAME_INSTR_OFFSET_MASK); |
|
388 ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); |
|
389 |
|
390 fp_register = reg_no; |
|
391 |
|
392 if (cie != NULL && cie->ci_initial_table != NULL) |
|
393 localregtab[reg_no] = |
|
394 cie->ci_initial_table->fr_reg[reg_no]; |
|
395 else if (!make_instr) { |
|
396 SIMPLE_ERROR_RETURN(DW_DLE_DF_MAKE_INSTR_NO_INIT); |
|
397 } |
|
398 |
|
399 break; |
|
400 } |
|
401 case DW_CFA_set_loc: |
|
402 { |
|
403 Dwarf_Addr new_loc = 0; |
|
404 |
|
405 READ_UNALIGNED(dbg, new_loc, Dwarf_Addr, |
|
406 instr_ptr, dbg->de_pointer_size); |
|
407 instr_ptr += dbg->de_pointer_size; |
|
408 if (new_loc != 0 && current_loc != 0) { |
|
409 /* Pre-relocation or before current_loc is set the |
|
410 test comparing new_loc and current_loc makes no |
|
411 sense. Testing for non-zero (above) is a way |
|
412 (fallible) to check that current_loc, new_loc |
|
413 are already relocated. */ |
|
414 if (new_loc <= current_loc) { |
|
415 /* Within a frame, address must increase. |
|
416 Seemingly it has not. Seems to be an error. */ |
|
417 |
|
418 SIMPLE_ERROR_RETURN |
|
419 (DW_DLE_DF_NEW_LOC_LESS_OLD_LOC); |
|
420 } |
|
421 } |
|
422 |
|
423 search_over = search_pc && (new_loc > search_pc_val); |
|
424 |
|
425 /* If gone past pc needed, retain old pc. */ |
|
426 if (!search_over) |
|
427 current_loc = new_loc; |
|
428 fp_offset = new_loc; |
|
429 break; |
|
430 } |
|
431 |
|
432 case DW_CFA_advance_loc1: |
|
433 { |
|
434 fp_offset = adv_loc = *(Dwarf_Small *) instr_ptr; |
|
435 instr_ptr += sizeof(Dwarf_Small); |
|
436 |
|
437 if (need_augmentation) { |
|
438 SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); |
|
439 } |
|
440 adv_loc *= code_alignment_factor; |
|
441 |
|
442 search_over = search_pc && |
|
443 (current_loc + adv_loc > search_pc_val); |
|
444 |
|
445 /* If gone past pc needed, retain old pc. */ |
|
446 if (!search_over) |
|
447 current_loc = current_loc + adv_loc; |
|
448 break; |
|
449 } |
|
450 |
|
451 case DW_CFA_advance_loc2: |
|
452 { |
|
453 READ_UNALIGNED(dbg, adv_loc, Dwarf_Unsigned, |
|
454 instr_ptr, sizeof(Dwarf_Half)); |
|
455 instr_ptr += sizeof(Dwarf_Half); |
|
456 fp_offset = adv_loc; |
|
457 |
|
458 if (need_augmentation) { |
|
459 SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); |
|
460 } |
|
461 adv_loc *= code_alignment_factor; |
|
462 |
|
463 search_over = search_pc && |
|
464 (current_loc + adv_loc > search_pc_val); |
|
465 |
|
466 /* If gone past pc needed, retain old pc. */ |
|
467 if (!search_over) |
|
468 current_loc = current_loc + adv_loc; |
|
469 break; |
|
470 } |
|
471 |
|
472 case DW_CFA_advance_loc4: |
|
473 { |
|
474 READ_UNALIGNED(dbg, adv_loc, Dwarf_Unsigned, |
|
475 instr_ptr, sizeof(Dwarf_ufixed)); |
|
476 instr_ptr += sizeof(Dwarf_ufixed); |
|
477 fp_offset = adv_loc; |
|
478 |
|
479 if (need_augmentation) { |
|
480 SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); |
|
481 } |
|
482 adv_loc *= code_alignment_factor; |
|
483 |
|
484 search_over = search_pc && |
|
485 (current_loc + adv_loc > search_pc_val); |
|
486 |
|
487 /* If gone past pc needed, retain old pc. */ |
|
488 if (!search_over) |
|
489 current_loc = current_loc + adv_loc; |
|
490 break; |
|
491 } |
|
492 |
|
493 case DW_CFA_offset_extended: |
|
494 { |
|
495 Dwarf_Unsigned lreg; |
|
496 |
|
497 DECODE_LEB128_UWORD(instr_ptr, lreg); |
|
498 reg_no = (reg_num_type) lreg; |
|
499 ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);; |
|
500 factored_N_value = |
|
501 _dwarf_decode_u_leb128(instr_ptr, &leb128_length); |
|
502 instr_ptr += leb128_length; |
|
503 |
|
504 if (need_augmentation) { |
|
505 SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); |
|
506 } |
|
507 localregtab[reg_no].ru_is_off = 1; |
|
508 localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET; |
|
509 localregtab[reg_no].ru_register = reg_num_of_cfa; |
|
510 localregtab[reg_no].ru_offset_or_block_len = factored_N_value * |
|
511 data_alignment_factor; |
|
512 |
|
513 fp_register = reg_no; |
|
514 fp_offset = factored_N_value; |
|
515 break; |
|
516 } |
|
517 |
|
518 case DW_CFA_restore_extended: |
|
519 { |
|
520 Dwarf_Unsigned lreg; |
|
521 |
|
522 DECODE_LEB128_UWORD(instr_ptr, lreg); |
|
523 reg_no = (reg_num_type) lreg; |
|
524 |
|
525 ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); |
|
526 |
|
527 if (cie != NULL && cie->ci_initial_table != NULL) { |
|
528 localregtab[reg_no] = cie->ci_initial_table->fr_reg[reg_no]; |
|
529 } else { |
|
530 if (!make_instr) { |
|
531 SIMPLE_ERROR_RETURN |
|
532 (DW_DLE_DF_MAKE_INSTR_NO_INIT); |
|
533 } |
|
534 } |
|
535 |
|
536 fp_register = reg_no; |
|
537 break; |
|
538 } |
|
539 |
|
540 case DW_CFA_undefined: |
|
541 { |
|
542 Dwarf_Unsigned lreg; |
|
543 |
|
544 DECODE_LEB128_UWORD(instr_ptr, lreg); |
|
545 reg_no = (reg_num_type) lreg; |
|
546 ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); |
|
547 |
|
548 localregtab[reg_no].ru_is_off = 0; |
|
549 localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET; |
|
550 localregtab[reg_no].ru_register = DW_FRAME_UNDEFINED_VAL; |
|
551 localregtab[reg_no].ru_offset_or_block_len = 0; |
|
552 |
|
553 fp_register = reg_no; |
|
554 break; |
|
555 } |
|
556 |
|
557 case DW_CFA_same_value: |
|
558 { |
|
559 Dwarf_Unsigned lreg; |
|
560 |
|
561 DECODE_LEB128_UWORD(instr_ptr, lreg); |
|
562 reg_no = (reg_num_type) lreg; |
|
563 ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); |
|
564 |
|
565 localregtab[reg_no].ru_is_off = 0; |
|
566 localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET; |
|
567 localregtab[reg_no].ru_register = DW_FRAME_SAME_VAL; |
|
568 localregtab[reg_no].ru_offset_or_block_len = 0; |
|
569 fp_register = reg_no; |
|
570 break; |
|
571 } |
|
572 |
|
573 case DW_CFA_register: |
|
574 { |
|
575 Dwarf_Unsigned lreg; |
|
576 reg_num_type reg_noA = 0; |
|
577 reg_num_type reg_noB = 0; |
|
578 |
|
579 DECODE_LEB128_UWORD(instr_ptr, lreg); |
|
580 reg_noA = (reg_num_type) lreg; |
|
581 |
|
582 ERROR_IF_REG_NUM_TOO_HIGH(reg_noA, reg_count); |
|
583 |
|
584 DECODE_LEB128_UWORD(instr_ptr, lreg); |
|
585 reg_noB = (reg_num_type) lreg; |
|
586 |
|
587 if (reg_noB > reg_count) { |
|
588 SIMPLE_ERROR_RETURN(DW_DLE_DF_REG_NUM_TOO_HIGH); |
|
589 } |
|
590 |
|
591 |
|
592 localregtab[reg_noA].ru_is_off = 0; |
|
593 localregtab[reg_noA].ru_value_type = DW_EXPR_OFFSET; |
|
594 localregtab[reg_noA].ru_register = reg_noB; |
|
595 localregtab[reg_noA].ru_offset_or_block_len = 0; |
|
596 |
|
597 fp_register = reg_noA; |
|
598 fp_offset = reg_noB; |
|
599 break; |
|
600 } |
|
601 |
|
602 case DW_CFA_remember_state: |
|
603 { |
|
604 stack_table = (Dwarf_Frame) |
|
605 _dwarf_get_alloc(dbg, DW_DLA_FRAME, 1); |
|
606 if (stack_table == NULL) { |
|
607 SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL); |
|
608 } |
|
609 |
|
610 for (i = 0; i < reg_count; i++) |
|
611 stack_table->fr_reg[i] = localregtab[i]; |
|
612 |
|
613 if (top_stack != NULL) |
|
614 stack_table->fr_next = top_stack; |
|
615 top_stack = stack_table; |
|
616 |
|
617 break; |
|
618 } |
|
619 |
|
620 case DW_CFA_restore_state: |
|
621 { |
|
622 if (top_stack == NULL) { |
|
623 SIMPLE_ERROR_RETURN(DW_DLE_DF_POP_EMPTY_STACK); |
|
624 } |
|
625 stack_table = top_stack; |
|
626 top_stack = stack_table->fr_next; |
|
627 |
|
628 for (i = 0; i < reg_count; i++) |
|
629 localregtab[i] = stack_table->fr_reg[i]; |
|
630 |
|
631 dwarf_dealloc(dbg, stack_table, DW_DLA_FRAME); |
|
632 break; |
|
633 } |
|
634 |
|
635 case DW_CFA_def_cfa: |
|
636 { |
|
637 Dwarf_Unsigned lreg; |
|
638 |
|
639 DECODE_LEB128_UWORD(instr_ptr, lreg); |
|
640 reg_no = (reg_num_type) lreg; |
|
641 |
|
642 ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); |
|
643 |
|
644 factored_N_value = |
|
645 _dwarf_decode_u_leb128(instr_ptr, &leb128_length); |
|
646 instr_ptr += leb128_length; |
|
647 |
|
648 if (need_augmentation) { |
|
649 SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); |
|
650 } |
|
651 cfa_reg.ru_is_off = 1; |
|
652 cfa_reg.ru_value_type = DW_EXPR_OFFSET; |
|
653 cfa_reg.ru_register = reg_no; |
|
654 cfa_reg.ru_offset_or_block_len = factored_N_value; |
|
655 |
|
656 fp_register = reg_no; |
|
657 fp_offset = factored_N_value; |
|
658 break; |
|
659 } |
|
660 |
|
661 case DW_CFA_def_cfa_register: |
|
662 { |
|
663 Dwarf_Unsigned lreg; |
|
664 |
|
665 DECODE_LEB128_UWORD(instr_ptr, lreg); |
|
666 reg_no = (reg_num_type) lreg; |
|
667 ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); |
|
668 |
|
669 cfa_reg.ru_register = reg_no; |
|
670 /* Do NOT set ru_offset_or_block_len or ru_is_off here. |
|
671 See dwarf2/3 spec. */ |
|
672 fp_register = reg_no; |
|
673 break; |
|
674 } |
|
675 |
|
676 case DW_CFA_def_cfa_offset: |
|
677 { |
|
678 factored_N_value = |
|
679 _dwarf_decode_u_leb128(instr_ptr, &leb128_length); |
|
680 instr_ptr += leb128_length; |
|
681 |
|
682 if (need_augmentation) { |
|
683 SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); |
|
684 } |
|
685 /* Do set ru_is_off here, as here factored_N_value |
|
686 counts. */ |
|
687 cfa_reg.ru_is_off = 1; |
|
688 cfa_reg.ru_value_type = DW_EXPR_OFFSET; |
|
689 cfa_reg.ru_offset_or_block_len = factored_N_value; |
|
690 |
|
691 fp_offset = factored_N_value; |
|
692 break; |
|
693 } |
|
694 case DW_CFA_nop: |
|
695 { |
|
696 break; |
|
697 } |
|
698 /* DWARF3 ops begin here. */ |
|
699 case DW_CFA_def_cfa_expression: |
|
700 { |
|
701 /* A single DW_FORM_block representing a dwarf |
|
702 expression. The form block establishes the way to |
|
703 compute the CFA. */ |
|
704 Dwarf_Unsigned block_len = 0; |
|
705 |
|
706 DECODE_LEB128_UWORD(instr_ptr, block_len); |
|
707 cfa_reg.ru_is_off = 0; /* arbitrary */ |
|
708 cfa_reg.ru_value_type = DW_EXPR_EXPRESSION; |
|
709 cfa_reg.ru_offset_or_block_len = block_len; |
|
710 cfa_reg.ru_block = instr_ptr; |
|
711 fp_offset = (Dwarf_Unsigned) instr_ptr; |
|
712 |
|
713 } |
|
714 break; |
|
715 case DW_CFA_expression: |
|
716 { |
|
717 /* An unsigned leb128 value is the first operand (a |
|
718 register number). The second operand is single |
|
719 DW_FORM_block representing a dwarf expression. The |
|
720 evaluator pushes the CFA on the evaluation stack |
|
721 then evaluates the expression to compute the value |
|
722 of the register contents. */ |
|
723 Dwarf_Unsigned lreg = 0; |
|
724 Dwarf_Unsigned block_len = 0; |
|
725 |
|
726 DECODE_LEB128_UWORD(instr_ptr, lreg); |
|
727 reg_no = (reg_num_type) lreg; |
|
728 ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); |
|
729 DECODE_LEB128_UWORD(instr_ptr, block_len); |
|
730 localregtab[lreg].ru_is_off = 0; /* arbitrary */ |
|
731 localregtab[lreg].ru_value_type = DW_EXPR_EXPRESSION; |
|
732 localregtab[lreg].ru_offset_or_block_len = block_len; |
|
733 localregtab[lreg].ru_block = instr_ptr; |
|
734 fp_offset = (Dwarf_Unsigned) instr_ptr; |
|
735 fp_register = reg_no; |
|
736 |
|
737 } |
|
738 break; |
|
739 case DW_CFA_cfa_offset_extended_sf: |
|
740 { |
|
741 /* The first operand is an unsigned leb128 register |
|
742 number. The second is a signed factored offset. |
|
743 Identical to DW_CFA_offset_extended except the |
|
744 secondoperand is signed */ |
|
745 Dwarf_Unsigned lreg; |
|
746 |
|
747 DECODE_LEB128_UWORD(instr_ptr, lreg); |
|
748 reg_no = (reg_num_type) lreg; |
|
749 ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); |
|
750 signed_factored_N_value = |
|
751 _dwarf_decode_s_leb128(instr_ptr, &leb128_length); |
|
752 instr_ptr += leb128_length; |
|
753 |
|
754 if (need_augmentation) { |
|
755 SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); |
|
756 } |
|
757 localregtab[reg_no].ru_is_off = 1; |
|
758 localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET; |
|
759 localregtab[reg_no].ru_register = reg_num_of_cfa; |
|
760 localregtab[reg_no].ru_offset_or_block_len = |
|
761 signed_factored_N_value * data_alignment_factor; |
|
762 |
|
763 fp_register = reg_no; |
|
764 fp_offset = signed_factored_N_value; |
|
765 } |
|
766 break; |
|
767 case DW_CFA_def_cfa_sf: |
|
768 { |
|
769 /* The first operand is an unsigned leb128 register |
|
770 number. The second is a signed leb128 factored |
|
771 offset. Identical to DW_CFA_def_cfa except that the |
|
772 second operand is signed and factored. */ |
|
773 Dwarf_Unsigned lreg; |
|
774 |
|
775 DECODE_LEB128_UWORD(instr_ptr, lreg); |
|
776 reg_no = (reg_num_type) lreg; |
|
777 ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); |
|
778 |
|
779 signed_factored_N_value = |
|
780 _dwarf_decode_s_leb128(instr_ptr, &leb128_length); |
|
781 instr_ptr += leb128_length; |
|
782 |
|
783 if (need_augmentation) { |
|
784 SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); |
|
785 } |
|
786 cfa_reg.ru_is_off = 1; |
|
787 cfa_reg.ru_value_type = DW_EXPR_OFFSET; |
|
788 cfa_reg.ru_register = reg_no; |
|
789 cfa_reg.ru_offset_or_block_len = |
|
790 signed_factored_N_value * data_alignment_factor; |
|
791 |
|
792 fp_register = reg_no; |
|
793 fp_offset = signed_factored_N_value; |
|
794 } |
|
795 break; |
|
796 case DW_CFA_def_cfa_offset_sf: |
|
797 { |
|
798 /* The operand is a signed leb128 operand representing |
|
799 a factored offset. Identical to |
|
800 DW_CFA_def_cfa_offset excep the operand is signed |
|
801 and factored. */ |
|
802 |
|
803 signed_factored_N_value = |
|
804 _dwarf_decode_s_leb128(instr_ptr, &leb128_length); |
|
805 instr_ptr += leb128_length; |
|
806 |
|
807 if (need_augmentation) { |
|
808 SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); |
|
809 } |
|
810 /* Do set ru_is_off here, as here factored_N_value |
|
811 counts. */ |
|
812 cfa_reg.ru_is_off = 1; |
|
813 cfa_reg.ru_value_type = DW_EXPR_OFFSET; |
|
814 cfa_reg.ru_offset_or_block_len = |
|
815 signed_factored_N_value * data_alignment_factor; |
|
816 |
|
817 fp_offset = signed_factored_N_value; |
|
818 } |
|
819 break; |
|
820 case DW_CFA_val_offset: |
|
821 { |
|
822 /* The first operand is an unsigned leb128 register |
|
823 number. The second is a factored unsigned offset. |
|
824 Makes the register be a val_offset(N) rule with N = |
|
825 factored_offset*data_alignment_factor. */ |
|
826 |
|
827 Dwarf_Unsigned lreg; |
|
828 |
|
829 DECODE_LEB128_UWORD(instr_ptr, lreg); |
|
830 reg_no = (reg_num_type) lreg; |
|
831 |
|
832 ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); |
|
833 |
|
834 factored_N_value = |
|
835 _dwarf_decode_u_leb128(instr_ptr, &leb128_length); |
|
836 instr_ptr += leb128_length; |
|
837 |
|
838 if (need_augmentation) { |
|
839 SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); |
|
840 } |
|
841 /* Do set ru_is_off here, as here factored_N_value |
|
842 counts. */ |
|
843 localregtab[reg_no].ru_is_off = 1; |
|
844 localregtab[reg_no].ru_register = reg_num_of_cfa; |
|
845 localregtab[reg_no].ru_value_type = DW_EXPR_VAL_OFFSET; |
|
846 localregtab[reg_no].ru_offset_or_block_len = |
|
847 factored_N_value * data_alignment_factor; |
|
848 |
|
849 fp_offset = factored_N_value; |
|
850 break; |
|
851 } |
|
852 case DW_CFA_val_offset_sf: |
|
853 { |
|
854 /* The first operand is an unsigned leb128 register |
|
855 number. The second is a factored signed offset. |
|
856 Makes the register be a val_offset(N) rule with N = |
|
857 factored_offset*data_alignment_factor. */ |
|
858 Dwarf_Unsigned lreg; |
|
859 |
|
860 DECODE_LEB128_UWORD(instr_ptr, lreg); |
|
861 reg_no = (reg_num_type) lreg; |
|
862 |
|
863 ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); |
|
864 signed_factored_N_value = |
|
865 _dwarf_decode_s_leb128(instr_ptr, &leb128_length); |
|
866 instr_ptr += leb128_length; |
|
867 |
|
868 if (need_augmentation) { |
|
869 SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); |
|
870 } |
|
871 /* Do set ru_is_off here, as here factored_N_value |
|
872 counts. */ |
|
873 localregtab[reg_no].ru_is_off = 1; |
|
874 localregtab[reg_no].ru_value_type = DW_EXPR_VAL_OFFSET; |
|
875 localregtab[reg_no].ru_offset_or_block_len = |
|
876 signed_factored_N_value * data_alignment_factor; |
|
877 |
|
878 fp_offset = signed_factored_N_value; |
|
879 |
|
880 } |
|
881 break; |
|
882 case DW_CFA_val_expression: |
|
883 { |
|
884 /* The first operand is an unsigned leb128 register |
|
885 number. The second is a DW_FORM_block representing a |
|
886 DWARF expression. The rule for the register number |
|
887 becomes a val_expression(E) rule. */ |
|
888 Dwarf_Unsigned lreg = 0; |
|
889 Dwarf_Unsigned block_len = 0; |
|
890 |
|
891 DECODE_LEB128_UWORD(instr_ptr, lreg); |
|
892 reg_no = (reg_num_type) lreg; |
|
893 ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); |
|
894 DECODE_LEB128_UWORD(instr_ptr, block_len); |
|
895 localregtab[lreg].ru_is_off = 0; /* arbitrary */ |
|
896 localregtab[lreg].ru_value_type = DW_EXPR_VAL_EXPRESSION; |
|
897 localregtab[lreg].ru_offset_or_block_len = block_len; |
|
898 localregtab[lreg].ru_block = instr_ptr; |
|
899 fp_offset = (Dwarf_Unsigned) instr_ptr; |
|
900 |
|
901 instr_ptr += block_len; |
|
902 fp_register = reg_no; |
|
903 |
|
904 } |
|
905 break; |
|
906 |
|
907 /* END DWARF3 new ops. */ |
|
908 |
|
909 |
|
910 #ifdef DW_CFA_GNU_window_save |
|
911 case DW_CFA_GNU_window_save: |
|
912 { |
|
913 /* no information: this just tells unwinder to restore |
|
914 the window registers from the previous frame's |
|
915 window save area */ |
|
916 break; |
|
917 } |
|
918 #endif |
|
919 #ifdef DW_CFA_GNU_args_size |
|
920 /* single uleb128 is the current arg area size in bytes. No |
|
921 register exists yet to save this in */ |
|
922 case DW_CFA_GNU_args_size: |
|
923 { |
|
924 Dwarf_Unsigned lreg; |
|
925 |
|
926 DECODE_LEB128_UWORD(instr_ptr, lreg); |
|
927 reg_no = (reg_num_type) lreg; |
|
928 |
|
929 break; |
|
930 } |
|
931 #endif |
|
932 default: |
|
933 /* ERROR, we have an opcode we know nothing about. Memory |
|
934 leak here, but an error like this is not supposed to |
|
935 happen so we ignore the leak. These used to be ignored, |
|
936 now we notice and report. */ |
|
937 SIMPLE_ERROR_RETURN(DW_DLE_DF_FRAME_DECODING_ERROR); |
|
938 |
|
939 } |
|
940 |
|
941 if (make_instr) { |
|
942 instr_count++; |
|
943 |
|
944 curr_instr = (Dwarf_Frame_Op *) |
|
945 _dwarf_get_alloc(dbg, DW_DLA_FRAME_OP, 1); |
|
946 if (curr_instr == NULL) { |
|
947 SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL); |
|
948 } |
|
949 |
|
950 curr_instr->fp_base_op = fp_base_op; |
|
951 curr_instr->fp_extended_op = fp_extended_op; |
|
952 curr_instr->fp_register = fp_register; |
|
953 curr_instr->fp_offset = fp_offset; |
|
954 curr_instr->fp_instr_offset = fp_instr_offset; |
|
955 |
|
956 curr_instr_item = (Dwarf_Chain) |
|
957 _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); |
|
958 if (curr_instr_item == NULL) { |
|
959 SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL); |
|
960 } |
|
961 |
|
962 curr_instr_item->ch_item = curr_instr; |
|
963 if (head_instr_chain == NULL) |
|
964 head_instr_chain = tail_instr_chain = curr_instr_item; |
|
965 else { |
|
966 tail_instr_chain->ch_next = curr_instr_item; |
|
967 tail_instr_chain = curr_instr_item; |
|
968 } |
|
969 } |
|
970 } |
|
971 |
|
972 /* |
|
973 If frame instruction decoding was right we would stop exactly at |
|
974 final_instr_ptr. */ |
|
975 if (instr_ptr > final_instr_ptr) { |
|
976 SIMPLE_ERROR_RETURN(DW_DLE_DF_FRAME_DECODING_ERROR); |
|
977 } |
|
978 |
|
979 /* Create the last row generated. */ |
|
980 if (table != NULL) { |
|
981 |
|
982 struct Dwarf_Reg_Rule_s *t2reg = table->fr_reg; |
|
983 struct Dwarf_Reg_Rule_s *t3reg = localregtab; |
|
984 struct Dwarf_Reg_Rule_s *t3end = t3reg + reg_count; |
|
985 |
|
986 table->fr_loc = current_loc; |
|
987 for (; t3reg < t3end; t3reg++, t2reg++) { |
|
988 *t2reg = *t3reg; |
|
989 } |
|
990 |
|
991 /* CONSTCOND */ |
|
992 if (reg_num_of_cfa < reg_count) { |
|
993 t2reg = table->fr_reg + reg_num_of_cfa; |
|
994 /* Update both the old DW_FRAME_CFA_COL row and the new |
|
995 fr_cfa_rule with the cfa_reg, this is the old-style |
|
996 update. */ |
|
997 *t2reg = cfa_reg; |
|
998 } |
|
999 table->fr_cfa_rule = cfa_reg; |
|
1000 } |
|
1001 |
|
1002 /* Dealloc anything remaining on stack. */ |
|
1003 for (; top_stack != NULL;) { |
|
1004 stack_table = top_stack; |
|
1005 top_stack = top_stack->fr_next; |
|
1006 dwarf_dealloc(dbg, stack_table, DW_DLA_FRAME); |
|
1007 } |
|
1008 |
|
1009 if (make_instr) { |
|
1010 /* Allocate list of pointers to Dwarf_Frame_Op's. */ |
|
1011 head_instr_block = (Dwarf_Frame_Op *) |
|
1012 _dwarf_get_alloc(dbg, DW_DLA_FRAME_BLOCK, instr_count); |
|
1013 if (head_instr_block == NULL) { |
|
1014 SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL); |
|
1015 } |
|
1016 |
|
1017 /* |
|
1018 Store pointers to Dwarf_Frame_Op's in this list and |
|
1019 deallocate the structs that chain the Dwarf_Frame_Op's. */ |
|
1020 curr_instr_item = head_instr_chain; |
|
1021 for (i = 0; i < instr_count; i++) { |
|
1022 *(head_instr_block + i) = |
|
1023 *(Dwarf_Frame_Op *) curr_instr_item->ch_item; |
|
1024 dealloc_instr_item = curr_instr_item; |
|
1025 curr_instr_item = curr_instr_item->ch_next; |
|
1026 dwarf_dealloc(dbg, dealloc_instr_item->ch_item, |
|
1027 DW_DLA_FRAME_OP); |
|
1028 dwarf_dealloc(dbg, dealloc_instr_item, DW_DLA_CHAIN); |
|
1029 } |
|
1030 *ret_frame_instr = head_instr_block; |
|
1031 |
|
1032 *returned_count = (Dwarf_Sword) instr_count; |
|
1033 } else { |
|
1034 *returned_count = 0; |
|
1035 } |
|
1036 free(localregtab); |
|
1037 return DW_DLV_OK; |
|
1038 #undef ERROR_IF_REG_NUM_TOO_HIGH |
|
1039 #undef SIMPLE_ERROR_RETURN |
|
1040 } |
|
1041 |
|
1042 /* Depending on version, either read the return address register |
|
1043 as a ubyte or as an leb number. |
|
1044 The form of this value changed for DWARF3. |
|
1045 */ |
|
1046 Dwarf_Unsigned |
|
1047 _dwarf_get_return_address_reg(Dwarf_Small * frame_ptr, |
|
1048 int version, unsigned long *size) |
|
1049 { |
|
1050 Dwarf_Unsigned uvalue = 0; |
|
1051 Dwarf_Word leb128_length = 0; |
|
1052 |
|
1053 if (version == 1) { |
|
1054 *size = 1; |
|
1055 uvalue = *(unsigned char *) frame_ptr; |
|
1056 return uvalue; |
|
1057 } |
|
1058 uvalue = _dwarf_decode_u_leb128(frame_ptr, &leb128_length); |
|
1059 *size = leb128_length; |
|
1060 return uvalue; |
|
1061 } |
|
1062 |
|
1063 |
|
1064 /* Trivial consumer function. |
|
1065 */ |
|
1066 int |
|
1067 dwarf_get_cie_of_fde(Dwarf_Fde fde, |
|
1068 Dwarf_Cie * cie_returned, Dwarf_Error * error) |
|
1069 { |
|
1070 if (fde == NULL) { |
|
1071 _dwarf_error(NULL, error, DW_DLE_FDE_NULL); |
|
1072 return (DW_DLV_ERROR); |
|
1073 } |
|
1074 |
|
1075 *cie_returned = fde->fd_cie; |
|
1076 return DW_DLV_OK; |
|
1077 |
|
1078 } |
|
1079 |
|
1080 /* |
|
1081 For g++ .eh_frame fde and cie. |
|
1082 the cie id is different as the |
|
1083 definition of the cie_id in an fde |
|
1084 is the distance back from the address of the |
|
1085 value to the cie. |
|
1086 Or 0 if this is a true cie. |
|
1087 Non standard dwarf, designed this way to be |
|
1088 convenient at run time for an allocated |
|
1089 (mapped into memory as part of the running image) section. |
|
1090 */ |
|
1091 int |
|
1092 dwarf_get_fde_list_eh(Dwarf_Debug dbg, |
|
1093 Dwarf_Cie ** cie_data, |
|
1094 Dwarf_Signed * cie_element_count, |
|
1095 Dwarf_Fde ** fde_data, |
|
1096 Dwarf_Signed * fde_element_count, |
|
1097 Dwarf_Error * error) |
|
1098 { |
|
1099 int res; |
|
1100 |
|
1101 res = |
|
1102 _dwarf_load_section(dbg, |
|
1103 dbg->de_debug_frame_eh_gnu_index, |
|
1104 &dbg->de_debug_frame_eh_gnu, error); |
|
1105 |
|
1106 if (res != DW_DLV_OK) { |
|
1107 return res; |
|
1108 } |
|
1109 |
|
1110 res = |
|
1111 _dwarf_get_fde_list_internal(dbg, |
|
1112 cie_data, |
|
1113 cie_element_count, |
|
1114 fde_data, |
|
1115 fde_element_count, |
|
1116 dbg->de_debug_frame_eh_gnu, |
|
1117 dbg->de_debug_frame_eh_gnu_index, |
|
1118 dbg->de_debug_frame_size_eh_gnu, |
|
1119 /* cie_id_value */ 0, |
|
1120 /* use_gnu_cie_calc= */ 1, |
|
1121 error); |
|
1122 return res; |
|
1123 } |
|
1124 |
|
1125 |
|
1126 |
|
1127 /* |
|
1128 For standard dwarf .debug_frame |
|
1129 cie_id is -1 in a cie, and |
|
1130 is the section offset in the .debug_frame section |
|
1131 of the cie otherwise. Standard dwarf |
|
1132 */ |
|
1133 int |
|
1134 dwarf_get_fde_list(Dwarf_Debug dbg, |
|
1135 Dwarf_Cie ** cie_data, |
|
1136 Dwarf_Signed * cie_element_count, |
|
1137 Dwarf_Fde ** fde_data, |
|
1138 Dwarf_Signed * fde_element_count, |
|
1139 Dwarf_Error * error) |
|
1140 { |
|
1141 int res; |
|
1142 |
|
1143 res = |
|
1144 _dwarf_load_section(dbg, |
|
1145 dbg->de_debug_frame_index, |
|
1146 &dbg->de_debug_frame, error); |
|
1147 |
|
1148 if (res != DW_DLV_OK) { |
|
1149 return res; |
|
1150 } |
|
1151 |
|
1152 res = |
|
1153 _dwarf_get_fde_list_internal(dbg, cie_data, |
|
1154 cie_element_count, |
|
1155 fde_data, |
|
1156 fde_element_count, |
|
1157 dbg->de_debug_frame, |
|
1158 dbg->de_debug_frame_index, |
|
1159 dbg->de_debug_frame_size, |
|
1160 DW_CIE_ID, |
|
1161 /* use_gnu_cie_calc= */ 0, |
|
1162 error); |
|
1163 |
|
1164 return res; |
|
1165 } |
|
1166 |
|
1167 |
|
1168 /* |
|
1169 Only works on dwarf sections, not eh_frame |
|
1170 Given a Dwarf_Die, see if it has a |
|
1171 DW_AT_MIPS_fde attribute and if so use that |
|
1172 to get an fde offset. |
|
1173 Then create a Dwarf_Fde to return thru the ret_fde pointer. |
|
1174 Also creates a cie (pointed at from the Dwarf_Fde). |
|
1175 */ |
|
1176 int |
|
1177 dwarf_get_fde_for_die(Dwarf_Debug dbg, |
|
1178 Dwarf_Die die, |
|
1179 Dwarf_Fde * ret_fde, Dwarf_Error * error) |
|
1180 { |
|
1181 Dwarf_Attribute attr; |
|
1182 Dwarf_Unsigned fde_offset = 0; |
|
1183 Dwarf_Signed signdval = 0; |
|
1184 Dwarf_Fde new_fde = 0; |
|
1185 unsigned char *fde_ptr = 0; |
|
1186 unsigned char *cie_ptr = 0; |
|
1187 Dwarf_Unsigned cie_id = 0; |
|
1188 |
|
1189 /* Fields for the current Cie being read. */ |
|
1190 int res; |
|
1191 int resattr; |
|
1192 int sdatares; |
|
1193 |
|
1194 struct cie_fde_prefix_s prefix; |
|
1195 struct cie_fde_prefix_s prefix_c; |
|
1196 |
|
1197 if (die == NULL) { |
|
1198 _dwarf_error(NULL, error, DW_DLE_DIE_NULL); |
|
1199 return (DW_DLV_ERROR); |
|
1200 } |
|
1201 |
|
1202 resattr = dwarf_attr(die, DW_AT_MIPS_fde, &attr, error); |
|
1203 if (resattr != DW_DLV_OK) { |
|
1204 return resattr; |
|
1205 } |
|
1206 |
|
1207 /* why is this formsdata? FIX */ |
|
1208 sdatares = dwarf_formsdata(attr, &signdval, error); |
|
1209 if (sdatares != DW_DLV_OK) { |
|
1210 return sdatares; |
|
1211 } |
|
1212 |
|
1213 res = |
|
1214 _dwarf_load_section(dbg, |
|
1215 dbg->de_debug_frame_index, |
|
1216 &dbg->de_debug_frame, error); |
|
1217 if (res != DW_DLV_OK) { |
|
1218 return res; |
|
1219 } |
|
1220 |
|
1221 fde_offset = signdval; |
|
1222 fde_ptr = (dbg->de_debug_frame + fde_offset); |
|
1223 |
|
1224 |
|
1225 /* First read in the 'common prefix' to figure out what * we are to |
|
1226 do with this entry. */ |
|
1227 memset(&prefix_c, 0, sizeof(prefix_c)); |
|
1228 memset(&prefix, 0, sizeof(prefix)); |
|
1229 res = dwarf_read_cie_fde_prefix(dbg, fde_ptr, |
|
1230 dbg->de_debug_frame, |
|
1231 dbg->de_debug_frame_index, |
|
1232 dbg->de_debug_frame_size, &prefix, |
|
1233 error); |
|
1234 if (res == DW_DLV_ERROR) { |
|
1235 return res; |
|
1236 } |
|
1237 if (res == DW_DLV_NO_ENTRY) |
|
1238 return res; |
|
1239 fde_ptr = prefix.cf_addr_after_prefix; |
|
1240 cie_id = prefix.cf_cie_id; |
|
1241 /* Pass NULL, not section pointer, for 3rd argument. de_debug_frame |
|
1242 has no eh_frame relevance. */ |
|
1243 res = dwarf_create_fde_from_after_start(dbg, &prefix, |
|
1244 (Dwarf_Small *) NULL, |
|
1245 fde_ptr, |
|
1246 /* use_gnu_cie_calc= */ 0, |
|
1247 /* Dwarf_Cie = */ 0, |
|
1248 &new_fde, error); |
|
1249 |
|
1250 if (res == DW_DLV_ERROR) { |
|
1251 return res; |
|
1252 } else if (res == DW_DLV_NO_ENTRY) { |
|
1253 return res; |
|
1254 } |
|
1255 /* DW_DLV_OK */ |
|
1256 |
|
1257 /* now read the cie corresponding to the fde */ |
|
1258 cie_ptr = new_fde->fd_section_ptr + cie_id; |
|
1259 res = dwarf_read_cie_fde_prefix(dbg, cie_ptr, |
|
1260 dbg->de_debug_frame, |
|
1261 dbg->de_debug_frame_index, |
|
1262 dbg->de_debug_frame_size, |
|
1263 &prefix_c, error); |
|
1264 if (res == DW_DLV_ERROR) { |
|
1265 return res; |
|
1266 } |
|
1267 if (res == DW_DLV_NO_ENTRY) |
|
1268 return res; |
|
1269 |
|
1270 cie_ptr = prefix_c.cf_addr_after_prefix; |
|
1271 cie_id = prefix_c.cf_cie_id; |
|
1272 |
|
1273 |
|
1274 if (cie_id == DW_CIE_ID) { |
|
1275 int res2 = 0; |
|
1276 Dwarf_Cie new_cie = 0; |
|
1277 |
|
1278 /* Pass NULL, not section pointer, for 3rd argument. |
|
1279 de_debug_frame has no eh_frame relevance. */ |
|
1280 res2 = dwarf_create_cie_from_after_start(dbg, |
|
1281 &prefix_c, |
|
1282 (Dwarf_Small *) NULL, |
|
1283 cie_ptr, |
|
1284 /* cie_count= */ 0, |
|
1285 /* use_gnu_cie_calc= */ |
|
1286 0, &new_cie, error); |
|
1287 if (res2 == DW_DLV_ERROR) { |
|
1288 dwarf_dealloc(dbg, new_fde, DW_DLA_FDE); |
|
1289 return res; |
|
1290 } else if (res2 == DW_DLV_NO_ENTRY) { |
|
1291 dwarf_dealloc(dbg, new_fde, DW_DLA_FDE); |
|
1292 return res; |
|
1293 } |
|
1294 |
|
1295 |
|
1296 new_fde->fd_cie = new_cie; |
|
1297 |
|
1298 } else { |
|
1299 _dwarf_error(dbg, error, DW_DLE_NO_CIE_FOR_FDE); |
|
1300 return (DW_DLV_ERROR); |
|
1301 } |
|
1302 |
|
1303 *ret_fde = new_fde; |
|
1304 return DW_DLV_OK; |
|
1305 } |
|
1306 |
|
1307 /* A dwarf consumer operation, see the consumer library documentation. |
|
1308 */ |
|
1309 int |
|
1310 dwarf_get_fde_range(Dwarf_Fde fde, |
|
1311 Dwarf_Addr * low_pc, |
|
1312 Dwarf_Unsigned * func_length, |
|
1313 Dwarf_Ptr * fde_bytes, |
|
1314 Dwarf_Unsigned * fde_byte_length, |
|
1315 Dwarf_Off * cie_offset, |
|
1316 Dwarf_Signed * cie_index, |
|
1317 Dwarf_Off * fde_offset, Dwarf_Error * error) |
|
1318 { |
|
1319 Dwarf_Debug dbg; |
|
1320 |
|
1321 if (fde == NULL) { |
|
1322 _dwarf_error(NULL, error, DW_DLE_FDE_NULL); |
|
1323 return (DW_DLV_ERROR); |
|
1324 } |
|
1325 |
|
1326 dbg = fde->fd_dbg; |
|
1327 if (dbg == NULL) { |
|
1328 _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL); |
|
1329 return (DW_DLV_ERROR); |
|
1330 } |
|
1331 |
|
1332 |
|
1333 /* We have always already done the section load here, so no need to |
|
1334 load the section. We did the section load in order to create the |
|
1335 Dwarf_Fde pointer passed in here. */ |
|
1336 |
|
1337 |
|
1338 if (low_pc != NULL) |
|
1339 *low_pc = fde->fd_initial_location; |
|
1340 if (func_length != NULL) |
|
1341 *func_length = fde->fd_address_range; |
|
1342 if (fde_bytes != NULL) |
|
1343 *fde_bytes = fde->fd_fde_start; |
|
1344 if (fde_byte_length != NULL) |
|
1345 *fde_byte_length = fde->fd_length; |
|
1346 if (cie_offset != NULL) |
|
1347 *cie_offset = fde->fd_cie_offset; |
|
1348 if (cie_index != NULL) |
|
1349 *cie_index = fde->fd_cie_index; |
|
1350 if (fde_offset != NULL) |
|
1351 *fde_offset = fde->fd_fde_start - fde->fd_section_ptr; |
|
1352 |
|
1353 return DW_DLV_OK; |
|
1354 } |
|
1355 |
|
1356 /* IRIX specific function. The exception tables |
|
1357 have C++ destructor information and are |
|
1358 at present undocumented. */ |
|
1359 int |
|
1360 dwarf_get_fde_exception_info(Dwarf_Fde fde, |
|
1361 Dwarf_Signed * |
|
1362 offset_into_exception_tables, |
|
1363 Dwarf_Error * error) |
|
1364 { |
|
1365 Dwarf_Debug dbg; |
|
1366 |
|
1367 dbg = fde->fd_dbg; |
|
1368 if (dbg == NULL) { |
|
1369 _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL); |
|
1370 return (DW_DLV_ERROR); |
|
1371 } |
|
1372 *offset_into_exception_tables = |
|
1373 fde->fd_offset_into_exception_tables; |
|
1374 return DW_DLV_OK; |
|
1375 } |
|
1376 |
|
1377 |
|
1378 /* A consumer code function. |
|
1379 Given a CIE pointer, return the normal CIE data thru |
|
1380 pointers. |
|
1381 Special augmentation data is not returned here. |
|
1382 */ |
|
1383 int |
|
1384 dwarf_get_cie_info(Dwarf_Cie cie, |
|
1385 Dwarf_Unsigned * bytes_in_cie, |
|
1386 Dwarf_Small * ptr_to_version, |
|
1387 char **augmenter, |
|
1388 Dwarf_Unsigned * code_alignment_factor, |
|
1389 Dwarf_Signed * data_alignment_factor, |
|
1390 Dwarf_Half * return_address_register, |
|
1391 Dwarf_Ptr * initial_instructions, |
|
1392 Dwarf_Unsigned * initial_instructions_length, |
|
1393 Dwarf_Error * error) |
|
1394 { |
|
1395 Dwarf_Debug dbg; |
|
1396 |
|
1397 if (cie == NULL) { |
|
1398 _dwarf_error(NULL, error, DW_DLE_CIE_NULL); |
|
1399 return (DW_DLV_ERROR); |
|
1400 } |
|
1401 |
|
1402 dbg = cie->ci_dbg; |
|
1403 if (dbg == NULL) { |
|
1404 _dwarf_error(NULL, error, DW_DLE_CIE_DBG_NULL); |
|
1405 return (DW_DLV_ERROR); |
|
1406 } |
|
1407 |
|
1408 if (ptr_to_version != NULL) |
|
1409 *ptr_to_version = cie->ci_cie_version_number; |
|
1410 if (augmenter != NULL) |
|
1411 *augmenter = cie->ci_augmentation; |
|
1412 if (code_alignment_factor != NULL) |
|
1413 *code_alignment_factor = cie->ci_code_alignment_factor; |
|
1414 if (data_alignment_factor != NULL) |
|
1415 *data_alignment_factor = cie->ci_data_alignment_factor; |
|
1416 if (return_address_register != NULL) |
|
1417 *return_address_register = cie->ci_return_address_register; |
|
1418 if (initial_instructions != NULL) |
|
1419 *initial_instructions = cie->ci_cie_instr_start; |
|
1420 if (initial_instructions_length != NULL) { |
|
1421 *initial_instructions_length = cie->ci_length + |
|
1422 cie->ci_length_size + |
|
1423 cie->ci_extension_size - |
|
1424 (cie->ci_cie_instr_start - cie->ci_cie_start); |
|
1425 |
|
1426 } |
|
1427 *bytes_in_cie = (cie->ci_length); |
|
1428 return (DW_DLV_OK); |
|
1429 } |
|
1430 |
|
1431 /* Return the register rules for all registers at a given pc. |
|
1432 */ |
|
1433 static int |
|
1434 _dwarf_get_fde_info_for_a_pc_row(Dwarf_Fde fde, |
|
1435 Dwarf_Addr pc_requested, |
|
1436 Dwarf_Frame table, |
|
1437 Dwarf_Half cfa_reg_col_num, |
|
1438 Dwarf_Error * error) |
|
1439 { |
|
1440 Dwarf_Debug dbg = 0; |
|
1441 Dwarf_Cie cie = 0; |
|
1442 int dw_err = 0; |
|
1443 Dwarf_Sword icount = 0; |
|
1444 int res = 0; |
|
1445 |
|
1446 if (fde == NULL) { |
|
1447 _dwarf_error(NULL, error, DW_DLE_FDE_NULL); |
|
1448 return (DW_DLV_ERROR); |
|
1449 } |
|
1450 |
|
1451 dbg = fde->fd_dbg; |
|
1452 if (dbg == NULL) { |
|
1453 _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL); |
|
1454 return (DW_DLV_ERROR); |
|
1455 } |
|
1456 |
|
1457 if (pc_requested < fde->fd_initial_location || |
|
1458 pc_requested >= |
|
1459 fde->fd_initial_location + fde->fd_address_range) { |
|
1460 _dwarf_error(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE); |
|
1461 return (DW_DLV_ERROR); |
|
1462 } |
|
1463 |
|
1464 cie = fde->fd_cie; |
|
1465 if (cie->ci_initial_table == NULL) { |
|
1466 cie->ci_initial_table = _dwarf_get_alloc(dbg, DW_DLA_FRAME, 1); |
|
1467 |
|
1468 if (cie->ci_initial_table == NULL) { |
|
1469 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); |
|
1470 return (DW_DLV_ERROR); |
|
1471 } |
|
1472 _dwarf_init_regrule_table(cie->ci_initial_table->fr_reg, |
|
1473 dbg->de_frame_reg_rules_entry_count, |
|
1474 dbg->de_frame_rule_initial_value); |
|
1475 _dwarf_init_regrule_table(&cie->ci_initial_table->fr_cfa_rule, |
|
1476 1, dbg->de_frame_rule_initial_value); |
|
1477 res = _dwarf_exec_frame_instr( /* make_instr= */ false, |
|
1478 /* ret_frame_instr= */ NULL, |
|
1479 /* search_pc */ false, |
|
1480 /* search_pc_val */ 0, |
|
1481 /* location */ 0, |
|
1482 cie->ci_cie_instr_start, |
|
1483 cie->ci_cie_instr_start + |
|
1484 (cie->ci_length + |
|
1485 cie->ci_length_size + |
|
1486 cie->ci_extension_size - |
|
1487 (cie->ci_cie_instr_start - |
|
1488 cie->ci_cie_start)), |
|
1489 cie->ci_initial_table, cie, dbg, |
|
1490 cfa_reg_col_num, &icount, |
|
1491 &dw_err); |
|
1492 if (res == DW_DLV_ERROR) { |
|
1493 _dwarf_error(dbg, error, dw_err); |
|
1494 return (res); |
|
1495 } else if (res == DW_DLV_NO_ENTRY) { |
|
1496 return res; |
|
1497 } |
|
1498 } |
|
1499 |
|
1500 { |
|
1501 Dwarf_Small *instr_end = fde->fd_fde_instr_start + |
|
1502 fde->fd_length + |
|
1503 fde->fd_length_size + |
|
1504 fde->fd_extension_size - (fde->fd_fde_instr_start - |
|
1505 fde->fd_fde_start); |
|
1506 |
|
1507 res = _dwarf_exec_frame_instr( /* make_instr= */ false, |
|
1508 /* ret_frame_instr= */ NULL, |
|
1509 /* search_pc */ true, |
|
1510 /* search_pc_val */ pc_requested, |
|
1511 fde->fd_initial_location, |
|
1512 fde->fd_fde_instr_start, |
|
1513 instr_end, |
|
1514 table, |
|
1515 cie, dbg, |
|
1516 cfa_reg_col_num, &icount, |
|
1517 &dw_err); |
|
1518 } |
|
1519 if (res == DW_DLV_ERROR) { |
|
1520 _dwarf_error(dbg, error, dw_err); |
|
1521 return (res); |
|
1522 } else if (res == DW_DLV_NO_ENTRY) { |
|
1523 return res; |
|
1524 } |
|
1525 |
|
1526 return DW_DLV_OK; |
|
1527 } |
|
1528 |
|
1529 /* A consumer call for efficiently getting the register info |
|
1530 for all registers in one call. |
|
1531 |
|
1532 The output table rules array is size DW_REG_TABLE_SIZE. |
|
1533 The frame info rules array in fde_table is of size |
|
1534 DW_REG_TABLE_SIZE too. |
|
1535 |
|
1536 This interface really only works well with MIPS/IRIX |
|
1537 where DW_FRAME_CFA_COL is zero (in that case it's safe). |
|
1538 |
|
1539 It is also restricted to the case where |
|
1540 DW_REG_TABLE_SIZE == DW_FRAME_LAST_REG_NUM == |
|
1541 dbg->de_frame_reg_rules_entry_count (true for MIPS/IRIX). |
|
1542 If this condition is not met calling this routine can result in |
|
1543 incorrect output or in memory corruption. |
|
1544 |
|
1545 */ |
|
1546 int |
|
1547 dwarf_get_fde_info_for_all_regs(Dwarf_Fde fde, |
|
1548 Dwarf_Addr pc_requested, |
|
1549 Dwarf_Regtable * reg_table, |
|
1550 Dwarf_Addr * row_pc, |
|
1551 Dwarf_Error * error) |
|
1552 { |
|
1553 |
|
1554 /* Table size: DW_REG_TABLE_SIZE */ |
|
1555 struct Dwarf_Frame_s fde_table; |
|
1556 Dwarf_Sword i = 0; |
|
1557 struct Dwarf_Reg_Rule_s *rule = NULL; |
|
1558 struct Dwarf_Regtable_Entry_s *out_rule = NULL; |
|
1559 int res = 0; |
|
1560 Dwarf_Debug dbg = 0; |
|
1561 |
|
1562 /* For this interface the size is fixed at compile time. */ |
|
1563 int output_table_real_data_size = DW_REG_TABLE_SIZE; |
|
1564 |
|
1565 FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg); |
|
1566 |
|
1567 res = dwarf_initialize_fde_table(dbg, &fde_table, |
|
1568 output_table_real_data_size, |
|
1569 error); |
|
1570 if (res != DW_DLV_OK) |
|
1571 return res; |
|
1572 |
|
1573 |
|
1574 |
|
1575 /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks |
|
1576 */ |
|
1577 res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, |
|
1578 &fde_table, |
|
1579 DW_FRAME_CFA_COL, error); |
|
1580 if (res != DW_DLV_OK) { |
|
1581 dwarf_free_fde_table(&fde_table); |
|
1582 return res; |
|
1583 } |
|
1584 |
|
1585 out_rule = ®_table->rules[0]; |
|
1586 rule = &fde_table.fr_reg[0]; |
|
1587 for (i = 0; i < output_table_real_data_size; |
|
1588 i++, ++out_rule, ++rule) { |
|
1589 out_rule->dw_offset_relevant = rule->ru_is_off; |
|
1590 out_rule->dw_value_type = rule->ru_value_type; |
|
1591 out_rule->dw_regnum = rule->ru_register; |
|
1592 out_rule->dw_offset = rule->ru_offset_or_block_len; |
|
1593 } |
|
1594 for (; i < DW_REG_TABLE_SIZE; ++i, ++out_rule) { |
|
1595 out_rule->dw_offset_relevant = 0; |
|
1596 out_rule->dw_value_type = DW_EXPR_OFFSET; |
|
1597 out_rule->dw_regnum = DW_FRAME_UNDEFINED_VAL; |
|
1598 out_rule->dw_offset = 0; |
|
1599 } |
|
1600 |
|
1601 /* The test is just in case it's not inside the table. For non-MIPS |
|
1602 it could be outside the table and that is just fine, it was |
|
1603 really a mistake to put it in the table in 1993. */ |
|
1604 /* CONSTCOND */ |
|
1605 if (DW_FRAME_CFA_COL < DW_REG_TABLE_SIZE) { |
|
1606 out_rule = ®_table->rules[DW_FRAME_CFA_COL]; |
|
1607 out_rule->dw_offset_relevant = fde_table.fr_cfa_rule.ru_is_off; |
|
1608 out_rule->dw_value_type = fde_table.fr_cfa_rule.ru_value_type; |
|
1609 out_rule->dw_regnum = fde_table.fr_cfa_rule.ru_register; |
|
1610 out_rule->dw_offset = |
|
1611 fde_table.fr_cfa_rule.ru_offset_or_block_len; |
|
1612 } |
|
1613 |
|
1614 if (row_pc != NULL) |
|
1615 *row_pc = fde_table.fr_loc; |
|
1616 dwarf_free_fde_table(&fde_table); |
|
1617 return DW_DLV_OK; |
|
1618 } |
|
1619 |
|
1620 /* A consumer call for efficiently getting the register info |
|
1621 for all registers in one call. |
|
1622 |
|
1623 The output table rules array is size output_table_real_data_size. |
|
1624 (normally DW_REG_TABLE_SIZE). |
|
1625 The frame info rules array in fde_table is normally of size |
|
1626 DW_FRAME_LAST_REG_NUM. |
|
1627 */ |
|
1628 int |
|
1629 dwarf_get_fde_info_for_all_regs3(Dwarf_Fde fde, |
|
1630 Dwarf_Addr pc_requested, |
|
1631 Dwarf_Regtable3 * reg_table, |
|
1632 Dwarf_Addr * row_pc, |
|
1633 Dwarf_Error * error) |
|
1634 { |
|
1635 |
|
1636 struct Dwarf_Frame_s fde_table; |
|
1637 Dwarf_Sword i = 0; |
|
1638 int res = 0; |
|
1639 struct Dwarf_Reg_Rule_s *rule = NULL; |
|
1640 struct Dwarf_Regtable_Entry3_s *out_rule = NULL; |
|
1641 Dwarf_Debug dbg = 0; |
|
1642 int output_table_real_data_size = reg_table->rt3_reg_table_size; |
|
1643 |
|
1644 FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg); |
|
1645 |
|
1646 output_table_real_data_size = |
|
1647 MIN(output_table_real_data_size, |
|
1648 dbg->de_frame_reg_rules_entry_count); |
|
1649 |
|
1650 res = dwarf_initialize_fde_table(dbg, &fde_table, |
|
1651 output_table_real_data_size, |
|
1652 error); |
|
1653 |
|
1654 /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks |
|
1655 */ |
|
1656 res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, |
|
1657 &fde_table, |
|
1658 DW_FRAME_CFA_COL3, error); |
|
1659 if (res != DW_DLV_OK) { |
|
1660 dwarf_free_fde_table(&fde_table); |
|
1661 return res; |
|
1662 } |
|
1663 |
|
1664 out_rule = ®_table->rt3_rules[0]; |
|
1665 rule = &fde_table.fr_reg[0]; |
|
1666 for (i = 0; i < output_table_real_data_size; |
|
1667 i++, ++out_rule, ++rule) { |
|
1668 out_rule->dw_offset_relevant = rule->ru_is_off; |
|
1669 out_rule->dw_value_type = rule->ru_value_type; |
|
1670 out_rule->dw_regnum = rule->ru_register; |
|
1671 out_rule->dw_offset_or_block_len = rule->ru_offset_or_block_len; |
|
1672 out_rule->dw_block_ptr = rule->ru_block; |
|
1673 } |
|
1674 for (; i < reg_table->rt3_reg_table_size; i++, ++out_rule) { |
|
1675 out_rule->dw_offset_relevant = 0; |
|
1676 out_rule->dw_value_type = DW_EXPR_OFFSET; |
|
1677 out_rule->dw_regnum = DW_FRAME_UNDEFINED_VAL; |
|
1678 out_rule->dw_offset_or_block_len = 0; |
|
1679 out_rule->dw_block_ptr = 0; |
|
1680 } |
|
1681 reg_table->rt3_cfa_rule.dw_offset_relevant = |
|
1682 fde_table.fr_cfa_rule.ru_is_off; |
|
1683 reg_table->rt3_cfa_rule.dw_value_type = |
|
1684 fde_table.fr_cfa_rule.ru_value_type; |
|
1685 reg_table->rt3_cfa_rule.dw_regnum = |
|
1686 fde_table.fr_cfa_rule.ru_register; |
|
1687 reg_table->rt3_cfa_rule.dw_offset_or_block_len = |
|
1688 fde_table.fr_cfa_rule.ru_offset_or_block_len; |
|
1689 reg_table->rt3_cfa_rule.dw_block_ptr = |
|
1690 fde_table.fr_cfa_rule.ru_block; |
|
1691 |
|
1692 if (row_pc != NULL) |
|
1693 *row_pc = fde_table.fr_loc; |
|
1694 |
|
1695 dwarf_free_fde_table(&fde_table); |
|
1696 return DW_DLV_OK; |
|
1697 } |
|
1698 |
|
1699 |
|
1700 /* Gets the register info for a single register at a given PC value |
|
1701 for the FDE specified. |
|
1702 |
|
1703 */ |
|
1704 int |
|
1705 dwarf_get_fde_info_for_reg(Dwarf_Fde fde, |
|
1706 Dwarf_Half table_column, |
|
1707 Dwarf_Addr pc_requested, |
|
1708 Dwarf_Signed * offset_relevant, |
|
1709 Dwarf_Signed * register_num, |
|
1710 Dwarf_Signed * offset, |
|
1711 Dwarf_Addr * row_pc, Dwarf_Error * error) |
|
1712 { |
|
1713 struct Dwarf_Frame_s fde_table; |
|
1714 int res; |
|
1715 Dwarf_Debug dbg = 0; |
|
1716 int output_table_real_data_size = 0; |
|
1717 |
|
1718 FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg); |
|
1719 output_table_real_data_size = dbg->de_frame_reg_rules_entry_count; |
|
1720 |
|
1721 res = dwarf_initialize_fde_table(dbg, &fde_table, |
|
1722 output_table_real_data_size, |
|
1723 error); |
|
1724 if (res != DW_DLV_OK) |
|
1725 return res; |
|
1726 |
|
1727 |
|
1728 if (table_column >= output_table_real_data_size) { |
|
1729 dwarf_free_fde_table(&fde_table); |
|
1730 _dwarf_error(dbg, error, DW_DLE_FRAME_TABLE_COL_BAD); |
|
1731 return (DW_DLV_ERROR); |
|
1732 } |
|
1733 |
|
1734 /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks |
|
1735 */ |
|
1736 res = |
|
1737 _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, &fde_table, |
|
1738 DW_FRAME_CFA_COL, error); |
|
1739 if (res != DW_DLV_OK) { |
|
1740 dwarf_free_fde_table(&fde_table); |
|
1741 return res; |
|
1742 } |
|
1743 |
|
1744 if (fde_table.fr_reg[table_column].ru_value_type != DW_EXPR_OFFSET) { |
|
1745 dwarf_free_fde_table(&fde_table); |
|
1746 _dwarf_error(NULL, error, |
|
1747 DW_DLE_FRAME_REGISTER_UNREPRESENTABLE); |
|
1748 return (DW_DLV_ERROR); |
|
1749 } |
|
1750 |
|
1751 if (register_num != NULL) |
|
1752 *register_num = fde_table.fr_reg[table_column].ru_register; |
|
1753 if (offset != NULL) |
|
1754 *offset = fde_table.fr_reg[table_column].ru_offset_or_block_len; |
|
1755 if (row_pc != NULL) |
|
1756 *row_pc = fde_table.fr_loc; |
|
1757 |
|
1758 *offset_relevant = (fde_table.fr_reg[table_column].ru_is_off); |
|
1759 dwarf_free_fde_table(&fde_table); |
|
1760 return DW_DLV_OK; |
|
1761 } |
|
1762 |
|
1763 /* In this interface, table_column of DW_FRAME_CFA_COL |
|
1764 is not meaningful. |
|
1765 Use dwarf_get_fde_info_for_cfa_reg3() to get the CFA. |
|
1766 */ |
|
1767 int |
|
1768 dwarf_get_fde_info_for_reg3(Dwarf_Fde fde, |
|
1769 Dwarf_Half table_column, |
|
1770 Dwarf_Addr pc_requested, |
|
1771 Dwarf_Small * value_type, |
|
1772 Dwarf_Signed * offset_relevant, |
|
1773 Dwarf_Signed * register_num, |
|
1774 Dwarf_Signed * offset_or_block_len, |
|
1775 Dwarf_Ptr * block_ptr, |
|
1776 Dwarf_Addr * row_pc_out, |
|
1777 Dwarf_Error * error) |
|
1778 { |
|
1779 struct Dwarf_Frame_s fde_table; |
|
1780 int res = 0; |
|
1781 |
|
1782 Dwarf_Debug dbg = 0; |
|
1783 int table_real_data_size = 0; |
|
1784 |
|
1785 FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg); |
|
1786 table_real_data_size = dbg->de_frame_reg_rules_entry_count; |
|
1787 res = dwarf_initialize_fde_table(dbg, &fde_table, |
|
1788 table_real_data_size, error); |
|
1789 if (res != DW_DLV_OK) |
|
1790 return res; |
|
1791 if (table_column >= table_real_data_size) { |
|
1792 dwarf_free_fde_table(&fde_table); |
|
1793 _dwarf_error(dbg, error, DW_DLE_FRAME_TABLE_COL_BAD); |
|
1794 return (DW_DLV_ERROR); |
|
1795 } |
|
1796 |
|
1797 /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks |
|
1798 */ |
|
1799 res = |
|
1800 _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, &fde_table, |
|
1801 DW_FRAME_CFA_COL3, error); |
|
1802 if (res != DW_DLV_OK) { |
|
1803 dwarf_free_fde_table(&fde_table); |
|
1804 return res; |
|
1805 } |
|
1806 |
|
1807 if (register_num != NULL) |
|
1808 *register_num = fde_table.fr_reg[table_column].ru_register; |
|
1809 if (offset_or_block_len != NULL) |
|
1810 *offset_or_block_len = |
|
1811 fde_table.fr_reg[table_column].ru_offset_or_block_len; |
|
1812 if (row_pc_out != NULL) |
|
1813 *row_pc_out = fde_table.fr_loc; |
|
1814 if (block_ptr) |
|
1815 *block_ptr = fde_table.fr_reg[table_column].ru_block; |
|
1816 |
|
1817 /* Without value_type the data cannot be understood, so we insist |
|
1818 on it being present, we don't test it. */ |
|
1819 *value_type = fde_table.fr_reg[table_column].ru_value_type; |
|
1820 *offset_relevant = (fde_table.fr_reg[table_column].ru_is_off); |
|
1821 dwarf_free_fde_table(&fde_table); |
|
1822 return DW_DLV_OK; |
|
1823 |
|
1824 } |
|
1825 |
|
1826 /* For latest DWARF, this is the preferred interface. |
|
1827 It more portably deals with the CFA by not |
|
1828 making the CFA a column number, which means |
|
1829 DW_FRAME_CFA_COL becomes an index like DW_CFA_SAME_VALUE, |
|
1830 a special value, not something one uses as an index. */ |
|
1831 int |
|
1832 dwarf_get_fde_info_for_cfa_reg3(Dwarf_Fde fde, |
|
1833 Dwarf_Addr pc_requested, |
|
1834 Dwarf_Small * value_type, |
|
1835 Dwarf_Signed * offset_relevant, |
|
1836 Dwarf_Signed * register_num, |
|
1837 Dwarf_Signed * offset_or_block_len, |
|
1838 Dwarf_Ptr * block_ptr, |
|
1839 Dwarf_Addr * row_pc_out, |
|
1840 Dwarf_Error * error) |
|
1841 { |
|
1842 struct Dwarf_Frame_s fde_table; |
|
1843 int res; |
|
1844 Dwarf_Debug dbg = 0; |
|
1845 |
|
1846 int table_real_data_size = 0; |
|
1847 |
|
1848 FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg); |
|
1849 |
|
1850 table_real_data_size = dbg->de_frame_reg_rules_entry_count; |
|
1851 res = dwarf_initialize_fde_table(dbg, &fde_table, |
|
1852 table_real_data_size, error); |
|
1853 if (res != DW_DLV_OK) |
|
1854 return res; |
|
1855 res = |
|
1856 _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, &fde_table, |
|
1857 DW_FRAME_CFA_COL3, error); |
|
1858 if (res != DW_DLV_OK) { |
|
1859 dwarf_free_fde_table(&fde_table); |
|
1860 return res; |
|
1861 } |
|
1862 |
|
1863 if (register_num != NULL) |
|
1864 *register_num = fde_table.fr_cfa_rule.ru_register; |
|
1865 if (offset_or_block_len != NULL) |
|
1866 *offset_or_block_len = |
|
1867 fde_table.fr_cfa_rule.ru_offset_or_block_len; |
|
1868 if (row_pc_out != NULL) |
|
1869 *row_pc_out = fde_table.fr_loc; |
|
1870 if (block_ptr) |
|
1871 *block_ptr = fde_table.fr_cfa_rule.ru_block; |
|
1872 |
|
1873 /* Without value_type the data cannot be understood, so we insist |
|
1874 on it being present, we don't test it. */ |
|
1875 *value_type = fde_table.fr_cfa_rule.ru_value_type; |
|
1876 *offset_relevant = fde_table.fr_cfa_rule.ru_is_off; |
|
1877 dwarf_free_fde_table(&fde_table); |
|
1878 return DW_DLV_OK; |
|
1879 } |
|
1880 |
|
1881 |
|
1882 |
|
1883 /* |
|
1884 Return pointer to the instructions in the dwarf |
|
1885 fde. |
|
1886 */ |
|
1887 int |
|
1888 dwarf_get_fde_instr_bytes(Dwarf_Fde inFde, Dwarf_Ptr * outinstraddr, |
|
1889 Dwarf_Unsigned * outaddrlen, |
|
1890 Dwarf_Error * error) |
|
1891 { |
|
1892 Dwarf_Unsigned len = 0; |
|
1893 unsigned char *instrs = 0; |
|
1894 Dwarf_Debug dbg = 0; |
|
1895 |
|
1896 if (inFde == NULL) { |
|
1897 _dwarf_error(dbg, error, DW_DLE_FDE_NULL); |
|
1898 return (DW_DLV_ERROR); |
|
1899 } |
|
1900 |
|
1901 dbg = inFde->fd_dbg; |
|
1902 if (dbg == NULL) { |
|
1903 _dwarf_error(dbg, error, DW_DLE_FDE_DBG_NULL); |
|
1904 return (DW_DLV_ERROR); |
|
1905 } |
|
1906 |
|
1907 instrs = inFde->fd_fde_instr_start; |
|
1908 |
|
1909 len = (inFde->fd_fde_start + inFde->fd_length + |
|
1910 inFde->fd_length_size + inFde->fd_extension_size) - instrs; |
|
1911 |
|
1912 *outinstraddr = instrs; |
|
1913 *outaddrlen = len; |
|
1914 return DW_DLV_OK; |
|
1915 } |
|
1916 |
|
1917 /* Allows getting an fde from its table via an index. |
|
1918 With more error checking than simply indexing oneself. |
|
1919 */ |
|
1920 int |
|
1921 dwarf_get_fde_n(Dwarf_Fde * fde_data, |
|
1922 Dwarf_Unsigned fde_index, |
|
1923 Dwarf_Fde * returned_fde, Dwarf_Error * error) |
|
1924 { |
|
1925 Dwarf_Debug dbg = 0; |
|
1926 |
|
1927 if (fde_data == NULL) { |
|
1928 _dwarf_error(dbg, error, DW_DLE_FDE_PTR_NULL); |
|
1929 return (DW_DLV_ERROR); |
|
1930 } |
|
1931 |
|
1932 FDE_NULL_CHECKS_AND_SET_DBG(*fde_data, dbg); |
|
1933 |
|
1934 if (fde_index >= dbg->de_fde_count) { |
|
1935 return (DW_DLV_NO_ENTRY); |
|
1936 } |
|
1937 *returned_fde = (*(fde_data + fde_index)); |
|
1938 return DW_DLV_OK; |
|
1939 } |
|
1940 |
|
1941 |
|
1942 /* |
|
1943 Lopc and hipc are extensions to the interface to |
|
1944 return the range of addresses that are described |
|
1945 by the returned fde. |
|
1946 */ |
|
1947 int |
|
1948 dwarf_get_fde_at_pc(Dwarf_Fde * fde_data, |
|
1949 Dwarf_Addr pc_of_interest, |
|
1950 Dwarf_Fde * returned_fde, |
|
1951 Dwarf_Addr * lopc, |
|
1952 Dwarf_Addr * hipc, Dwarf_Error * error) |
|
1953 { |
|
1954 Dwarf_Debug dbg = NULL; |
|
1955 Dwarf_Fde fde = NULL; |
|
1956 Dwarf_Fde entryfde = NULL; |
|
1957 |
|
1958 if (fde_data == NULL) { |
|
1959 _dwarf_error(NULL, error, DW_DLE_FDE_PTR_NULL); |
|
1960 return (DW_DLV_ERROR); |
|
1961 } |
|
1962 |
|
1963 /* Assumes fde_data table has at least one entry. */ |
|
1964 entryfde = *fde_data; |
|
1965 FDE_NULL_CHECKS_AND_SET_DBG(entryfde, dbg); |
|
1966 |
|
1967 if (dbg == NULL) { |
|
1968 _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL); |
|
1969 return (DW_DLV_ERROR); |
|
1970 } |
|
1971 { |
|
1972 /* The fde's are sorted by their addresses. Binary search to |
|
1973 find correct fde. */ |
|
1974 Dwarf_Signed low = 0; |
|
1975 Dwarf_Signed high = dbg->de_fde_count - 1L; |
|
1976 Dwarf_Signed middle = 0; |
|
1977 Dwarf_Fde cur_fde; |
|
1978 |
|
1979 while (low <= high) { |
|
1980 middle = (low + high) / 2; |
|
1981 cur_fde = fde_data[middle]; |
|
1982 if (pc_of_interest < cur_fde->fd_initial_location) { |
|
1983 high = middle - 1; |
|
1984 } else if (pc_of_interest >= |
|
1985 (cur_fde->fd_initial_location + |
|
1986 cur_fde->fd_address_range)) { |
|
1987 low = middle + 1; |
|
1988 } else { |
|
1989 fde = fde_data[middle]; |
|
1990 break; |
|
1991 } |
|
1992 } |
|
1993 } |
|
1994 |
|
1995 if (fde) { |
|
1996 if (lopc != NULL) |
|
1997 *lopc = fde->fd_initial_location; |
|
1998 if (hipc != NULL) |
|
1999 *hipc = |
|
2000 fde->fd_initial_location + fde->fd_address_range - 1; |
|
2001 *returned_fde = fde; |
|
2002 return (DW_DLV_OK); |
|
2003 } |
|
2004 |
|
2005 return (DW_DLV_NO_ENTRY); |
|
2006 } |
|
2007 |
|
2008 |
|
2009 /* Expands a single frame instruction block |
|
2010 into a n array of Dwarf_Frame_Op-s. |
|
2011 */ |
|
2012 int |
|
2013 dwarf_expand_frame_instructions(Dwarf_Debug dbg, |
|
2014 Dwarf_Ptr instruction, |
|
2015 Dwarf_Unsigned i_length, |
|
2016 Dwarf_Frame_Op ** returned_op_list, |
|
2017 Dwarf_Signed * returned_op_count, |
|
2018 Dwarf_Error * error) |
|
2019 { |
|
2020 Dwarf_Sword instr_count; |
|
2021 int res; |
|
2022 int dw_err; |
|
2023 |
|
2024 if (dbg == 0) { |
|
2025 _dwarf_error(NULL, error, DW_DLE_DBG_NULL); |
|
2026 return (DW_DLV_ERROR); |
|
2027 } |
|
2028 |
|
2029 if (returned_op_list == 0 || returned_op_count == 0) { |
|
2030 _dwarf_error(dbg, error, DW_DLE_RET_OP_LIST_NULL); |
|
2031 return (DW_DLV_ERROR); |
|
2032 } |
|
2033 |
|
2034 /* The cast to Dwarf_Ptr may get a compiler warning, but it is safe |
|
2035 as it is just an i_length offset from 'instruction' itself. A |
|
2036 caller has made a big mistake if the result is not a valid |
|
2037 pointer. */ |
|
2038 res = _dwarf_exec_frame_instr( /* make_instr= */ true, |
|
2039 returned_op_list, |
|
2040 /* search_pc */ false, |
|
2041 /* search_pc_val */ 0, |
|
2042 /* location */ 0, |
|
2043 instruction, |
|
2044 (Dwarf_Ptr) ((Dwarf_Unsigned) |
|
2045 instruction + i_length), |
|
2046 /* Dwarf_Frame */ NULL, |
|
2047 /* cie_ptr */ NULL, |
|
2048 dbg, |
|
2049 DW_FRAME_CFA_COL, &instr_count, |
|
2050 &dw_err); |
|
2051 if (res != DW_DLV_OK) { |
|
2052 if (res == DW_DLV_ERROR) { |
|
2053 _dwarf_error(dbg, error, dw_err); |
|
2054 } |
|
2055 return (res); |
|
2056 } |
|
2057 |
|
2058 *returned_op_count = instr_count; |
|
2059 return DW_DLV_OK; |
|
2060 } |
|
2061 |
|
2062 |
|
2063 /* Used by dwarfdump -v to print offsets, for debugging |
|
2064 dwarf info. |
|
2065 The dwarf_ version is preferred over the obsolete _dwarf version. |
|
2066 _dwarf version kept for compatibility. |
|
2067 */ |
|
2068 /* ARGSUSED 4 */ |
|
2069 int |
|
2070 _dwarf_fde_section_offset(Dwarf_Debug dbg, Dwarf_Fde in_fde, |
|
2071 Dwarf_Off * fde_off, Dwarf_Off * cie_off, |
|
2072 Dwarf_Error * err) |
|
2073 { |
|
2074 return _dwarf_fde_section_offset(dbg,in_fde,fde_off, |
|
2075 cie_off,err); |
|
2076 } |
|
2077 /* ARGSUSED 4 */ |
|
2078 int |
|
2079 dwarf_fde_section_offset(Dwarf_Debug dbg, Dwarf_Fde in_fde, |
|
2080 Dwarf_Off * fde_off, Dwarf_Off * cie_off, |
|
2081 Dwarf_Error * err) |
|
2082 { |
|
2083 char *start = 0; |
|
2084 char *loc = 0; |
|
2085 |
|
2086 |
|
2087 |
|
2088 start = (char *) in_fde->fd_section_ptr; |
|
2089 loc = (char *) in_fde->fd_fde_start; |
|
2090 |
|
2091 *fde_off = (loc - start); |
|
2092 *cie_off = in_fde->fd_cie_offset; |
|
2093 return DW_DLV_OK; |
|
2094 } |
|
2095 |
|
2096 /* Used by dwarfdump -v to print offsets, for debugging |
|
2097 dwarf info. |
|
2098 The dwarf_ version is preferred over the obsolete _dwarf version. |
|
2099 _dwarf version kept for compatibility. |
|
2100 */ |
|
2101 /* ARGSUSED 4 */ |
|
2102 int |
|
2103 _dwarf_cie_section_offset(Dwarf_Debug dbg, Dwarf_Cie in_cie, |
|
2104 Dwarf_Off * cie_off, Dwarf_Error * err) |
|
2105 { |
|
2106 return dwarf_cie_section_offset(dbg,in_cie,cie_off,err); |
|
2107 } |
|
2108 /* ARGSUSED 4 */ |
|
2109 int |
|
2110 dwarf_cie_section_offset(Dwarf_Debug dbg, Dwarf_Cie in_cie, |
|
2111 Dwarf_Off * cie_off, Dwarf_Error * err) |
|
2112 { |
|
2113 char *start = 0; |
|
2114 char *loc = 0; |
|
2115 |
|
2116 start = (char *) in_cie->ci_section_ptr; |
|
2117 loc = (char *) in_cie->ci_cie_start; |
|
2118 |
|
2119 *cie_off = (loc - start); |
|
2120 return DW_DLV_OK; |
|
2121 } |
|
2122 |
|
2123 /* Returns a pointer to target-specific augmentation data thru augdata |
|
2124 and returns the length of the data thru augdata_len. |
|
2125 |
|
2126 It's up to the consumer code to know how to interpret the bytes |
|
2127 of target-specific data (endian issues apply too, these |
|
2128 are just raw bytes pointed to). |
|
2129 See Linux Standard Base Core Specification version 3.0 for |
|
2130 the details on .eh_frame info. |
|
2131 |
|
2132 Returns DW_DLV_ERROR if fde is NULL or some other serious |
|
2133 error. |
|
2134 Returns DW_DLV_NO_ENTRY if there is no target-specific |
|
2135 augmentation data. |
|
2136 |
|
2137 The bytes pointed to are in the Dwarf_Cie, and as long as that |
|
2138 is valid the bytes are there. No 'dealloc' call is needed |
|
2139 for the bytes. |
|
2140 */ |
|
2141 int |
|
2142 dwarf_get_cie_augmentation_data(Dwarf_Cie cie, |
|
2143 Dwarf_Small ** augdata, |
|
2144 Dwarf_Unsigned * augdata_len, |
|
2145 Dwarf_Error * error) |
|
2146 { |
|
2147 if (cie == NULL) { |
|
2148 _dwarf_error(NULL, error, DW_DLE_CIE_NULL); |
|
2149 return (DW_DLV_ERROR); |
|
2150 } |
|
2151 if (cie->ci_gnu_eh_augmentation_len == 0) { |
|
2152 return DW_DLV_NO_ENTRY; |
|
2153 } |
|
2154 *augdata = (Dwarf_Small *) (cie->ci_gnu_eh_augmentation_bytes); |
|
2155 *augdata_len = cie->ci_gnu_eh_augmentation_len; |
|
2156 return DW_DLV_OK; |
|
2157 } |
|
2158 |
|
2159 |
|
2160 /* Returns a pointer to target-specific augmentation data thru augdata |
|
2161 and returns the length of the data thru augdata_len. |
|
2162 |
|
2163 It's up to the consumer code to know how to interpret the bytes |
|
2164 of target-specific data (endian issues apply too, these |
|
2165 are just raw bytes pointed to). |
|
2166 See Linux Standard Base Core Specification version 3.0 for |
|
2167 the details on .eh_frame info. |
|
2168 |
|
2169 Returns DW_DLV_ERROR if fde is NULL or some other serious |
|
2170 error. |
|
2171 Returns DW_DLV_NO_ENTRY if there is no target-specific |
|
2172 augmentation data. |
|
2173 |
|
2174 The bytes pointed to are in the Dwarf_Fde, and as long as that |
|
2175 is valid the bytes are there. No 'dealloc' call is needed |
|
2176 for the bytes. |
|
2177 |
|
2178 */ |
|
2179 int |
|
2180 dwarf_get_fde_augmentation_data(Dwarf_Fde fde, |
|
2181 Dwarf_Small * *augdata, |
|
2182 Dwarf_Unsigned * augdata_len, |
|
2183 Dwarf_Error * error) |
|
2184 { |
|
2185 Dwarf_Cie cie = 0; |
|
2186 |
|
2187 if (fde == NULL) { |
|
2188 _dwarf_error(NULL, error, DW_DLE_FDE_NULL); |
|
2189 return (DW_DLV_ERROR); |
|
2190 } |
|
2191 cie = fde->fd_cie; |
|
2192 if (cie == NULL) { |
|
2193 _dwarf_error(NULL, error, DW_DLE_CIE_NULL); |
|
2194 return (DW_DLV_ERROR); |
|
2195 } |
|
2196 if (cie->ci_gnu_eh_augmentation_len == 0) { |
|
2197 return DW_DLV_NO_ENTRY; |
|
2198 } |
|
2199 *augdata = (Dwarf_Small *) fde->fd_gnu_eh_augmentation_bytes; |
|
2200 *augdata_len = fde->fd_gnu_eh_augmentation_len; |
|
2201 return DW_DLV_OK; |
|
2202 } |
|
2203 |
|
2204 |
|
2205 /* Initialize with same_value , a value which makes sense |
|
2206 for IRIX/MIPS. |
|
2207 The correct value to use is ABI dependent. |
|
2208 For register-windows machines most |
|
2209 or all registers should get DW_FRAME_UNDEFINED_VAL as the |
|
2210 correct initial value. |
|
2211 Some think DW_FRAME_UNDEFINED_VAL is always the |
|
2212 right value. |
|
2213 |
|
2214 For some ABIs a setting which varies by register |
|
2215 would be more appropriate. |
|
2216 |
|
2217 FIXME. */ |
|
2218 |
|
2219 static void |
|
2220 _dwarf_init_regrule_table(struct Dwarf_Reg_Rule_s *t1reg, |
|
2221 int last_reg_num, int initial_value) |
|
2222 { |
|
2223 struct Dwarf_Reg_Rule_s *t1end = t1reg + last_reg_num; |
|
2224 |
|
2225 for (; t1reg < t1end; t1reg++) { |
|
2226 t1reg->ru_is_off = 0; |
|
2227 t1reg->ru_value_type = DW_EXPR_OFFSET; |
|
2228 t1reg->ru_register = initial_value; |
|
2229 t1reg->ru_offset_or_block_len = 0; |
|
2230 t1reg->ru_block = 0; |
|
2231 } |
|
2232 } |
|
2233 |
|
2234 #if 0 |
|
2235 /* Used solely for debugging libdwarf. */ |
|
2236 static void |
|
2237 dump_frame_rule(char *msg, struct Dwarf_Reg_Rule_s *reg_rule) |
|
2238 { |
|
2239 printf |
|
2240 ("%s type %s (0x%x), is_off %d reg %d offset 0x%llx blockp 0x%llx \n", |
|
2241 msg, |
|
2242 (reg_rule->ru_value_type == |
|
2243 DW_EXPR_OFFSET) ? "DW_EXPR_OFFSET" : (reg_rule-> |
|
2244 ru_value_type == |
|
2245 DW_EXPR_VAL_OFFSET) ? |
|
2246 "DW_EXPR_VAL_OFFSET" : (reg_rule->ru_value_type == |
|
2247 DW_EXPR_VAL_EXPRESSION) ? |
|
2248 "DW_EXPR_VAL_EXPRESSION" : (reg_rule->ru_value_type == |
|
2249 DW_EXPR_EXPRESSION) ? |
|
2250 "DW_EXPR_EXPRESSION" : "Unknown", |
|
2251 (unsigned) reg_rule->ru_value_type, (int) reg_rule->ru_is_off, |
|
2252 (int) reg_rule->ru_register, |
|
2253 (unsigned long long) reg_rule->ru_offset_or_block_len, |
|
2254 (unsigned long long) reg_rule->ru_block); |
|
2255 return; |
|
2256 } |
|
2257 #endif |
|
2258 |
|
2259 /* This allows consumers to set the 'initial value' so that |
|
2260 an ISA/ABI specific default can be used, dynamically, |
|
2261 at run time. Useful for dwarfdump and non-MIPS architectures.. |
|
2262 The value defaults to one of |
|
2263 DW_FRAME_SAME_VALUE or DW_FRAME_UNKNOWN_VALUE |
|
2264 but dwarfdump can dump multiple ISA/ABI objects so |
|
2265 we may want to get this set to what the ABI says is correct. |
|
2266 |
|
2267 Returns the value that was present before we changed it here. |
|
2268 */ |
|
2269 |
|
2270 Dwarf_Half |
|
2271 dwarf_set_frame_rule_inital_value(Dwarf_Debug dbg, Dwarf_Half value) |
|
2272 { |
|
2273 Dwarf_Half orig = dbg->de_frame_rule_initial_value; |
|
2274 |
|
2275 dbg->de_frame_rule_initial_value = value; |
|
2276 return orig; |
|
2277 } |
|
2278 |
|
2279 /* This allows consumers to set the array size of the reg rules |
|
2280 table so that |
|
2281 an ISA/ABI specific value can be used, dynamically, |
|
2282 at run time. Useful for non-MIPS archtectures. |
|
2283 The value defaults to DW_FRAME_LAST_REG_NUM. |
|
2284 but dwarfdump can dump multiple ISA/ABI objects so |
|
2285 consumers want to get this set to what the ABI says is correct. |
|
2286 |
|
2287 Returns the value that was present before we changed it here. |
|
2288 */ |
|
2289 |
|
2290 Dwarf_Half |
|
2291 dwarf_set_frame_rule_table_size(Dwarf_Debug dbg, Dwarf_Half value) |
|
2292 { |
|
2293 Dwarf_Half orig = dbg->de_frame_reg_rules_entry_count; |
|
2294 |
|
2295 dbg->de_frame_reg_rules_entry_count = value; |
|
2296 return orig; |
|
2297 } |
|
2298 |
|
2299 |
|
2300 static int |
|
2301 dwarf_initialize_fde_table(Dwarf_Debug dbg, |
|
2302 struct Dwarf_Frame_s *fde_table, |
|
2303 unsigned table_real_data_size, |
|
2304 Dwarf_Error * error) |
|
2305 { |
|
2306 unsigned entry_size = sizeof(struct Dwarf_Frame_s); |
|
2307 |
|
2308 fde_table->fr_loc = 0; |
|
2309 fde_table->fr_reg_count = table_real_data_size; |
|
2310 fde_table->fr_next = 0; |
|
2311 |
|
2312 fde_table->fr_reg = (struct Dwarf_Reg_Rule_s *) |
|
2313 calloc(entry_size, table_real_data_size); |
|
2314 if (fde_table->fr_reg == 0) { |
|
2315 _dwarf_error(dbg, error, DW_DLE_DF_ALLOC_FAIL); |
|
2316 return (DW_DLV_ERROR); |
|
2317 } |
|
2318 return DW_DLV_OK; |
|
2319 |
|
2320 } |
|
2321 static void |
|
2322 dwarf_free_fde_table(struct Dwarf_Frame_s *fde_table) |
|
2323 { |
|
2324 free(fde_table->fr_reg); |
|
2325 fde_table->fr_reg_count = 0; |
|
2326 fde_table->fr_reg = 0; |
|
2327 } |
|
2328 |
|
2329 |
|
2330 /* Return DW_DLV_OK if we succeed. else return DW_DLV_ERROR. |
|
2331 */ |
|
2332 int |
|
2333 _dwarf_frame_constructor(Dwarf_Debug dbg, void *frame) |
|
2334 { |
|
2335 struct Dwarf_Frame_s *fp = frame; |
|
2336 |
|
2337 if (!dbg) { |
|
2338 return DW_DLV_ERROR; |
|
2339 } |
|
2340 |
|
2341 fp->fr_reg = calloc(dbg->de_frame_reg_rules_entry_count, |
|
2342 sizeof(struct Dwarf_Reg_Rule_s)); |
|
2343 if (!fp->fr_reg) { |
|
2344 return DW_DLV_ERROR; |
|
2345 } |
|
2346 fp->fr_reg_count = dbg->de_frame_reg_rules_entry_count; |
|
2347 return DW_DLV_OK; |
|
2348 } |
|
2349 |
|
2350 void |
|
2351 _dwarf_frame_destructor(void *frame) |
|
2352 { |
|
2353 struct Dwarf_Frame_s *fp = frame; |
|
2354 |
|
2355 if (fp->fr_reg) |
|
2356 free(fp->fr_reg); |
|
2357 fp->fr_reg = 0; |
|
2358 fp->fr_reg_count = 0; |
|
2359 } |