|
1 /* |
|
2 Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved. |
|
3 Portions Copyright (C) 2007 David Anderson. 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 of the GNU General Public License as |
|
7 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 General Public License along |
|
21 with this program; if not, write the Free Software Foundation, Inc., 51 |
|
22 Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. |
|
23 |
|
24 Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, |
|
25 Mountain View, CA 94043, or: |
|
26 |
|
27 http://www.sgi.com |
|
28 |
|
29 For further information regarding this notice, see: |
|
30 |
|
31 http://oss.sgi.com/projects/GenInfo/NoticeExplan |
|
32 |
|
33 |
|
34 |
|
35 $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_frames.c,v 1.5 2006/06/14 20:34:02 davea Exp $ */ |
|
36 |
|
37 /* The address of the Free Software Foundation is |
|
38 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, |
|
39 Boston, MA 02110-1301, USA. |
|
40 SGI has moved from the Crittenden Lane address. |
|
41 */ |
|
42 |
|
43 |
|
44 |
|
45 #include "globals.h" |
|
46 |
|
47 #include "print_frames.h" |
|
48 #include "dwconf.h" |
|
49 #include "esb.h" |
|
50 |
|
51 |
|
52 static void |
|
53 print_one_frame_reg_col(Dwarf_Debug dbg, |
|
54 Dwarf_Unsigned rule_id, |
|
55 Dwarf_Small value_type, |
|
56 Dwarf_Unsigned reg_used, |
|
57 struct dwconf_s *config_data, |
|
58 Dwarf_Signed offset_relevant, |
|
59 Dwarf_Signed offset, Dwarf_Ptr block_ptr); |
|
60 |
|
61 /* |
|
62 Gather the fde print logic here so the control logic |
|
63 determining what FDE to print is clearer. |
|
64 */ |
|
65 int |
|
66 print_one_fde(Dwarf_Debug dbg, Dwarf_Fde fde, |
|
67 Dwarf_Unsigned fde_index, |
|
68 Dwarf_Cie * cie_data, |
|
69 Dwarf_Signed cie_element_count, |
|
70 Dwarf_Half address_size, int is_eh, |
|
71 struct dwconf_s *config_data) |
|
72 { |
|
73 Dwarf_Addr j = 0; |
|
74 Dwarf_Addr low_pc = 0; |
|
75 Dwarf_Unsigned func_length = 0; |
|
76 Dwarf_Ptr fde_bytes = NULL; |
|
77 Dwarf_Unsigned fde_bytes_length = 0; |
|
78 Dwarf_Off cie_offset = 0; |
|
79 Dwarf_Signed cie_index = 0; |
|
80 Dwarf_Off fde_offset = 0; |
|
81 Dwarf_Signed eh_table_offset = 0; |
|
82 int fres = 0; |
|
83 int offres = 0; |
|
84 string temps = 0; |
|
85 Dwarf_Error err = 0; |
|
86 int printed_intro_addr = 0; |
|
87 |
|
88 fres = dwarf_get_fde_range(fde, |
|
89 &low_pc, &func_length, |
|
90 &fde_bytes, |
|
91 &fde_bytes_length, |
|
92 &cie_offset, &cie_index, |
|
93 &fde_offset, &err); |
|
94 if (fres == DW_DLV_ERROR) { |
|
95 print_error(dbg, "dwarf_get_fde_range", fres, err); |
|
96 } |
|
97 if (fres == DW_DLV_NO_ENTRY) { |
|
98 return DW_DLV_NO_ENTRY; |
|
99 } |
|
100 if (cu_name_flag && |
|
101 fde_offset_for_cu_low != DW_DLV_BADOFFSET && |
|
102 (fde_offset < fde_offset_for_cu_low || |
|
103 fde_offset > fde_offset_for_cu_high)) { |
|
104 return DW_DLV_NO_ENTRY; |
|
105 } |
|
106 /* eh_table_offset is IRIX ONLY. */ |
|
107 fres = dwarf_get_fde_exception_info(fde, &eh_table_offset, &err); |
|
108 if (fres == DW_DLV_ERROR) { |
|
109 print_error(dbg, "dwarf_get_fde_exception_info", fres, err); |
|
110 } |
|
111 temps = get_fde_proc_name(dbg, low_pc); |
|
112 printf |
|
113 ("<%3lld><%#llx:%#llx><%s><fde offset 0x%llx length: 0x%llx>", |
|
114 cie_index, low_pc, (low_pc + func_length), |
|
115 temps ? temps : "", fde_offset, fde_bytes_length); |
|
116 |
|
117 |
|
118 if (!is_eh) { |
|
119 /* IRIX uses eh_table_offset. */ |
|
120 if (eh_table_offset == DW_DLX_NO_EH_OFFSET) { |
|
121 printf("<eh offset %s>\n", "none"); |
|
122 } else if (eh_table_offset == DW_DLX_EH_OFFSET_UNAVAILABLE) { |
|
123 printf("<eh offset %s>\n", "unknown"); |
|
124 } else { |
|
125 printf("<eh offset 0x%llx>\n", eh_table_offset); |
|
126 } |
|
127 } else { |
|
128 int ares = 0; |
|
129 Dwarf_Small *data = 0; |
|
130 Dwarf_Unsigned len = 0; |
|
131 |
|
132 ares = dwarf_get_fde_augmentation_data(fde, &data, &len, &err); |
|
133 if (ares == DW_DLV_NO_ENTRY) { |
|
134 /* do nothing. */ |
|
135 } else if (ares == DW_DLV_OK) { |
|
136 int k2; |
|
137 |
|
138 printf("<eh aug data len 0x%llx", (long long) len); |
|
139 for (k2 = 0; k2 < len; ++k2) { |
|
140 if (k2 == 0) { |
|
141 printf(" bytes 0x"); |
|
142 } |
|
143 printf("%02x ", (unsigned char) data[k2]); |
|
144 } |
|
145 printf(">"); |
|
146 } /* else DW_DLV_ERROR, do nothing */ |
|
147 printf("\n"); |
|
148 } |
|
149 /* call dwarf_get_fde_info_for_reg() to get whole matrix */ |
|
150 |
|
151 for (j = low_pc; j < low_pc + func_length; j++) { |
|
152 Dwarf_Half k; |
|
153 |
|
154 if (config_data->cf_interface_number == 3) { |
|
155 Dwarf_Signed reg = 0; |
|
156 Dwarf_Signed offset_relevant = 0; |
|
157 Dwarf_Small value_type = 0; |
|
158 Dwarf_Signed offset_or_block_len = 0; |
|
159 Dwarf_Signed offset = 0; |
|
160 Dwarf_Ptr block_ptr = 0; |
|
161 Dwarf_Addr row_pc = 0; |
|
162 |
|
163 int fires = dwarf_get_fde_info_for_cfa_reg3(fde, |
|
164 j, |
|
165 &value_type, |
|
166 &offset_relevant, |
|
167 ®, |
|
168 &offset_or_block_len, |
|
169 &block_ptr, |
|
170 &row_pc, |
|
171 &err); |
|
172 |
|
173 offset = offset_or_block_len; |
|
174 if (fires == DW_DLV_ERROR) { |
|
175 print_error(dbg, |
|
176 "dwarf_get_fde_info_for_reg", fires, err); |
|
177 } |
|
178 if (fires == DW_DLV_NO_ENTRY) { |
|
179 continue; |
|
180 } |
|
181 if (row_pc != j) { |
|
182 /* duplicate row */ |
|
183 continue; |
|
184 } |
|
185 if (!printed_intro_addr) { |
|
186 printf(" %08llx:\t", j); |
|
187 printed_intro_addr = 1; |
|
188 } |
|
189 print_one_frame_reg_col(dbg, config_data->cf_cfa_reg, |
|
190 value_type, |
|
191 reg, |
|
192 config_data, |
|
193 offset_relevant, offset, block_ptr); |
|
194 } |
|
195 for (k = 0; k < config_data->cf_table_entry_count; k++) { |
|
196 Dwarf_Signed reg = 0; |
|
197 Dwarf_Signed offset_relevant = 0; |
|
198 int fires = 0; |
|
199 Dwarf_Small value_type = 0; |
|
200 Dwarf_Ptr block_ptr = 0; |
|
201 Dwarf_Signed offset_or_block_len = 0; |
|
202 Dwarf_Signed offset = 0; |
|
203 Dwarf_Addr row_pc = 0; |
|
204 |
|
205 if (config_data->cf_interface_number == 3) { |
|
206 |
|
207 fires = dwarf_get_fde_info_for_reg3(fde, |
|
208 k, |
|
209 j, |
|
210 &value_type, |
|
211 &offset_relevant, |
|
212 ®, |
|
213 &offset_or_block_len, |
|
214 &block_ptr, |
|
215 &row_pc, &err); |
|
216 offset = offset_or_block_len; |
|
217 } else { /* ASSERT: |
|
218 config_data->cf_interface_number == |
|
219 2 */ |
|
220 |
|
221 |
|
222 value_type = DW_EXPR_OFFSET; |
|
223 fires = dwarf_get_fde_info_for_reg(fde, |
|
224 k, |
|
225 j, |
|
226 &offset_relevant, |
|
227 ®, |
|
228 &offset, &row_pc, |
|
229 &err); |
|
230 } |
|
231 if (fires == DW_DLV_ERROR) { |
|
232 printf("\n"); |
|
233 print_error(dbg, |
|
234 "dwarf_get_fde_info_for_reg", fires, err); |
|
235 } |
|
236 if (fires == DW_DLV_NO_ENTRY) { |
|
237 continue; |
|
238 } |
|
239 if (row_pc != j) { |
|
240 /* duplicate row */ |
|
241 break; |
|
242 } |
|
243 if (!printed_intro_addr) { |
|
244 printf(" %08llx:\t", j); |
|
245 printed_intro_addr = 1; |
|
246 } |
|
247 print_one_frame_reg_col(dbg,k, |
|
248 value_type, |
|
249 reg, |
|
250 config_data, |
|
251 offset_relevant, offset, block_ptr); |
|
252 |
|
253 } |
|
254 if (printed_intro_addr) { |
|
255 printf("\n"); |
|
256 printed_intro_addr = 0; |
|
257 } |
|
258 } |
|
259 if (verbose > 1) { |
|
260 Dwarf_Off fde_off; |
|
261 Dwarf_Off cie_off; |
|
262 |
|
263 /* get the fde instructions and print them in raw form, just |
|
264 like cie instructions */ |
|
265 Dwarf_Ptr instrs; |
|
266 Dwarf_Unsigned ilen; |
|
267 int res; |
|
268 |
|
269 res = dwarf_get_fde_instr_bytes(fde, &instrs, &ilen, &err); |
|
270 offres = |
|
271 dwarf_fde_section_offset(dbg, fde, &fde_off, &cie_off, |
|
272 &err); |
|
273 if (offres == DW_DLV_OK) { |
|
274 printf("\tfde sec. offset %llu 0x%llx" |
|
275 " cie offset for fde: %llu 0x%llx\n", |
|
276 (unsigned long long) fde_off, |
|
277 (unsigned long long) fde_off, |
|
278 (unsigned long long) cie_off, |
|
279 (unsigned long long) cie_off); |
|
280 |
|
281 } |
|
282 |
|
283 |
|
284 if (res == DW_DLV_OK) { |
|
285 int cires = 0; |
|
286 Dwarf_Unsigned cie_length = 0; |
|
287 Dwarf_Small version = 0; |
|
288 string augmenter; |
|
289 Dwarf_Unsigned code_alignment_factor = 0; |
|
290 Dwarf_Signed data_alignment_factor = 0; |
|
291 Dwarf_Half return_address_register_rule = 0; |
|
292 Dwarf_Ptr initial_instructions = 0; |
|
293 Dwarf_Unsigned initial_instructions_length = 0; |
|
294 |
|
295 if (cie_index >= cie_element_count) { |
|
296 printf("Bad cie index %lld with fde index %lld! " |
|
297 "(table entry max %lld)\n", |
|
298 (long long) cie_index, (long long) fde_index, |
|
299 (long long) cie_element_count); |
|
300 exit(1); |
|
301 } |
|
302 |
|
303 cires = dwarf_get_cie_info(cie_data[cie_index], |
|
304 &cie_length, |
|
305 &version, |
|
306 &augmenter, |
|
307 &code_alignment_factor, |
|
308 &data_alignment_factor, |
|
309 &return_address_register_rule, |
|
310 &initial_instructions, |
|
311 &initial_instructions_length, |
|
312 &err); |
|
313 if (cires == DW_DLV_ERROR) { |
|
314 printf |
|
315 ("Bad cie index %lld with fde index %lld!\n", |
|
316 (long long) cie_index, (long long) fde_index); |
|
317 print_error(dbg, "dwarf_get_cie_info", cires, err); |
|
318 } |
|
319 if (cires == DW_DLV_NO_ENTRY) { |
|
320 ; /* ? */ |
|
321 } else { |
|
322 |
|
323 print_frame_inst_bytes(dbg, instrs, |
|
324 (Dwarf_Signed) ilen, |
|
325 data_alignment_factor, |
|
326 (int) code_alignment_factor, |
|
327 address_size, config_data); |
|
328 } |
|
329 } else if (res == DW_DLV_NO_ENTRY) { |
|
330 printf |
|
331 ("Impossible: no instr bytes for fde index %d?\n", |
|
332 (int) fde_index); |
|
333 } else { |
|
334 /* DW_DLV_ERROR */ |
|
335 printf |
|
336 ("Error: on gettinginstr bytes for fde index %d?\n", |
|
337 (int) fde_index); |
|
338 print_error(dbg, "dwarf_get_fde_instr_bytes", res, err); |
|
339 } |
|
340 |
|
341 } |
|
342 return DW_DLV_OK; |
|
343 } |
|
344 |
|
345 |
|
346 /* Print a cie. Gather the print logic here so the |
|
347 control logic deciding what to print |
|
348 is clearer. |
|
349 */ |
|
350 int |
|
351 print_one_cie(Dwarf_Debug dbg, Dwarf_Cie cie, |
|
352 Dwarf_Unsigned cie_index, Dwarf_Half address_size, |
|
353 struct dwconf_s *config_data) |
|
354 { |
|
355 |
|
356 int cires = 0; |
|
357 Dwarf_Unsigned cie_length = 0; |
|
358 Dwarf_Small version = 0; |
|
359 string augmenter = ""; |
|
360 Dwarf_Unsigned code_alignment_factor = 0; |
|
361 Dwarf_Signed data_alignment_factor = 0; |
|
362 Dwarf_Half return_address_register_rule = 0; |
|
363 Dwarf_Ptr initial_instructions = 0; |
|
364 Dwarf_Unsigned initial_instructions_length = 0; |
|
365 Dwarf_Off cie_off = 0; |
|
366 Dwarf_Error err = 0; |
|
367 |
|
368 cires = dwarf_get_cie_info(cie, |
|
369 &cie_length, |
|
370 &version, |
|
371 &augmenter, |
|
372 &code_alignment_factor, |
|
373 &data_alignment_factor, |
|
374 &return_address_register_rule, |
|
375 &initial_instructions, |
|
376 &initial_instructions_length, &err); |
|
377 if (cires == DW_DLV_ERROR) { |
|
378 print_error(dbg, "dwarf_get_cie_info", cires, err); |
|
379 } |
|
380 if (cires == DW_DLV_NO_ENTRY) { |
|
381 ; /* ? */ |
|
382 printf("Impossible DW_DLV_NO_ENTRY on cie %d\n", |
|
383 (int) cie_index); |
|
384 return DW_DLV_NO_ENTRY; |
|
385 } |
|
386 { |
|
387 printf("<%3lld>\tversion\t\t\t\t%d\n", cie_index, version); |
|
388 cires = dwarf_cie_section_offset(dbg, cie, &cie_off, &err); |
|
389 if (cires == DW_DLV_OK) { |
|
390 printf("\tcie sec. offset %llu 0x%llx\n", |
|
391 (unsigned long long) cie_off, |
|
392 (unsigned long long) cie_off); |
|
393 |
|
394 } |
|
395 |
|
396 printf("\taugmentation\t\t\t%s\n", augmenter); |
|
397 printf("\tcode_alignment_factor\t\t%llu\n", |
|
398 (unsigned long long) code_alignment_factor); |
|
399 printf("\tdata_alignment_factor\t\t%lld\n", |
|
400 (long long) data_alignment_factor); |
|
401 printf("\treturn_address_register\t\t%d\n", |
|
402 (int) return_address_register_rule); |
|
403 { |
|
404 int ares = 0; |
|
405 Dwarf_Small *data = 0; |
|
406 Dwarf_Unsigned len = 0; |
|
407 |
|
408 ares = |
|
409 dwarf_get_cie_augmentation_data(cie, &data, &len, &err); |
|
410 if (ares == DW_DLV_NO_ENTRY) { |
|
411 /* do nothing. */ |
|
412 } else if (ares == DW_DLV_OK && len > 0) { |
|
413 int k2; |
|
414 |
|
415 printf("\teh aug data len 0x%llx", (long long) len); |
|
416 for (k2 = 0; data && k2 < len; ++k2) { |
|
417 if (k2 == 0) { |
|
418 printf(" bytes 0x"); |
|
419 } |
|
420 printf("%02x ", (unsigned char) data[k2]); |
|
421 } |
|
422 printf("\n"); |
|
423 } /* else DW_DLV_ERROR or no data, do |
|
424 nothing */ |
|
425 } |
|
426 |
|
427 printf |
|
428 ("\tbytes of initial instructions:\t%lld\n", |
|
429 (long long) initial_instructions_length); |
|
430 printf("\tcie length :\t\t\t%lld\n", (long long) cie_length); |
|
431 print_frame_inst_bytes(dbg, initial_instructions, (Dwarf_Signed) |
|
432 initial_instructions_length, |
|
433 data_alignment_factor, |
|
434 (int) code_alignment_factor, |
|
435 address_size, config_data); |
|
436 } |
|
437 return DW_DLV_OK; |
|
438 } |
|
439 |
|
440 void |
|
441 get_string_from_locs(Dwarf_Debug dbg, |
|
442 Dwarf_Ptr bytes_in, |
|
443 Dwarf_Unsigned block_len,struct esb_s *out_string) |
|
444 { |
|
445 |
|
446 Dwarf_Locdesc *locdescarray = 0; |
|
447 Dwarf_Signed listlen = 0; |
|
448 Dwarf_Error err2 =0; |
|
449 int skip_locdesc_header=1; |
|
450 int res2 = dwarf_loclist_from_expr(dbg, |
|
451 bytes_in,block_len, |
|
452 &locdescarray, |
|
453 &listlen,&err2); |
|
454 if (res2 == DW_DLV_ERROR) { |
|
455 print_error(dbg, "dwarf_get_loclist_from_expr", |
|
456 res2, err2); |
|
457 } |
|
458 if(res2==DW_DLV_NO_ENTRY) { |
|
459 return; |
|
460 } |
|
461 /* lcnt is always 1 */ |
|
462 |
|
463 /* Use locdescarray here.*/ |
|
464 int res = dwarfdump_print_one_locdesc(dbg, |
|
465 locdescarray, |
|
466 skip_locdesc_header, |
|
467 out_string); |
|
468 if(res != DW_DLV_OK) { |
|
469 printf("Bad status from _dwarf_print_one_locdesc %d\n",res); |
|
470 exit(1); |
|
471 } |
|
472 |
|
473 |
|
474 |
|
475 dwarf_dealloc(dbg, locdescarray->ld_s, DW_DLA_LOC_BLOCK); |
|
476 dwarf_dealloc(dbg, locdescarray, DW_DLA_LOCDESC); |
|
477 |
|
478 |
|
479 return ; |
|
480 } |
|
481 |
|
482 /* Print the frame instructions in detail for a glob of instructions. |
|
483 */ |
|
484 |
|
485 /*ARGSUSED*/ void |
|
486 print_frame_inst_bytes(Dwarf_Debug dbg, |
|
487 Dwarf_Ptr cie_init_inst, Dwarf_Signed len, |
|
488 Dwarf_Signed data_alignment_factor, |
|
489 int code_alignment_factor, Dwarf_Half addr_size, |
|
490 struct dwconf_s *config_data) |
|
491 { |
|
492 unsigned char *instp = (unsigned char *) cie_init_inst; |
|
493 Dwarf_Unsigned uval; |
|
494 Dwarf_Unsigned uval2; |
|
495 unsigned int uleblen; |
|
496 unsigned int off = 0; |
|
497 unsigned int loff = 0; |
|
498 unsigned short u16; |
|
499 unsigned int u32; |
|
500 unsigned long long u64; |
|
501 |
|
502 for (; len > 0;) { |
|
503 unsigned char ibyte = *instp; |
|
504 int top = ibyte & 0xc0; |
|
505 int bottom = ibyte & 0x3f; |
|
506 int delta; |
|
507 int reg; |
|
508 |
|
509 switch (top) { |
|
510 case DW_CFA_advance_loc: |
|
511 delta = ibyte & 0x3f; |
|
512 printf("\t%2u DW_CFA_advance_loc %d", off, |
|
513 (int) (delta * code_alignment_factor)); |
|
514 if (verbose) { |
|
515 printf(" (%d * %d)", (int) delta, |
|
516 (int) code_alignment_factor); |
|
517 } |
|
518 printf("\n"); |
|
519 break; |
|
520 case DW_CFA_offset: |
|
521 loff = off; |
|
522 reg = ibyte & 0x3f; |
|
523 uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); |
|
524 instp += uleblen; |
|
525 len -= uleblen; |
|
526 off += uleblen; |
|
527 printf("\t%2u DW_CFA_offset ", loff); |
|
528 printreg((Dwarf_Signed) reg, config_data); |
|
529 printf(" %lld", (signed long long) |
|
530 (((Dwarf_Signed) uval) * data_alignment_factor)); |
|
531 if (verbose) { |
|
532 printf(" (%llu * %d)", (unsigned long long) uval, |
|
533 (int) data_alignment_factor); |
|
534 } |
|
535 printf("\n"); |
|
536 break; |
|
537 |
|
538 case DW_CFA_restore: |
|
539 reg = ibyte & 0x3f; |
|
540 printf("\t%2u DW_CFA_restore \n", off); |
|
541 printreg((Dwarf_Signed) reg, config_data); |
|
542 printf("\n"); |
|
543 break; |
|
544 |
|
545 default: |
|
546 loff = off; |
|
547 switch (bottom) { |
|
548 case DW_CFA_set_loc: |
|
549 /* operand is address, so need address size */ |
|
550 /* which will be 4 or 8. */ |
|
551 switch (addr_size) { |
|
552 case 4: |
|
553 { |
|
554 __uint32_t v32; |
|
555 |
|
556 memcpy(&v32, instp + 1, addr_size); |
|
557 uval = v32; |
|
558 } |
|
559 break; |
|
560 case 8: |
|
561 { |
|
562 __uint64_t v64; |
|
563 |
|
564 memcpy(&v64, instp + 1, addr_size); |
|
565 uval = v64; |
|
566 } |
|
567 break; |
|
568 default: |
|
569 printf |
|
570 ("Error: Unexpected address size %d in DW_CFA_set_loc!\n", |
|
571 addr_size); |
|
572 uval = 0; |
|
573 } |
|
574 |
|
575 instp += addr_size; |
|
576 len -= (Dwarf_Signed) addr_size; |
|
577 off += addr_size; |
|
578 printf("\t%2u DW_CFA_set_loc %llu\n", |
|
579 loff, (unsigned long long) uval); |
|
580 break; |
|
581 case DW_CFA_advance_loc1: |
|
582 delta = (unsigned char) *(instp + 1); |
|
583 uval2 = delta; |
|
584 instp += 1; |
|
585 len -= 1; |
|
586 off += 1; |
|
587 printf("\t%2u DW_CFA_advance_loc1 %llu\n", |
|
588 loff, (unsigned long long) uval2); |
|
589 break; |
|
590 case DW_CFA_advance_loc2: |
|
591 memcpy(&u16, instp + 1, 2); |
|
592 uval2 = u16; |
|
593 instp += 2; |
|
594 len -= 2; |
|
595 off += 2; |
|
596 printf("\t%2u DW_CFA_advance_loc2 %llu\n", |
|
597 loff, (unsigned long long) uval2); |
|
598 break; |
|
599 case DW_CFA_advance_loc4: |
|
600 memcpy(&u32, instp + 1, 4); |
|
601 uval2 = u32; |
|
602 instp += 4; |
|
603 len -= 4; |
|
604 off += 4; |
|
605 printf("\t%2u DW_CFA_advance_loc4 %llu\n", |
|
606 loff, (unsigned long long) uval2); |
|
607 break; |
|
608 case DW_CFA_MIPS_advance_loc8: |
|
609 memcpy(&u64, instp + 1, 8); |
|
610 uval2 = u64; |
|
611 instp += 8; |
|
612 len -= 8; |
|
613 off += 8; |
|
614 printf("\t%2u DW_CFA_MIPS_advance_loc8 %llu\n", |
|
615 loff, (unsigned long long) uval2); |
|
616 break; |
|
617 case DW_CFA_offset_extended: |
|
618 uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); |
|
619 instp += uleblen; |
|
620 len -= uleblen; |
|
621 off += uleblen; |
|
622 uval2 = |
|
623 local_dwarf_decode_u_leb128(instp + 1, &uleblen); |
|
624 instp += uleblen; |
|
625 len -= uleblen; |
|
626 off += uleblen; |
|
627 printf("\t%2u DW_CFA_offset_extended ", loff); |
|
628 printreg((Dwarf_Signed) uval, config_data); |
|
629 printf(" %lld", (signed long long) |
|
630 (((Dwarf_Signed) uval2) * |
|
631 data_alignment_factor)); |
|
632 if (verbose) { |
|
633 printf(" (%llu * %d)", (unsigned long long) uval2, |
|
634 (int) data_alignment_factor); |
|
635 } |
|
636 printf("\n"); |
|
637 break; |
|
638 |
|
639 case DW_CFA_restore_extended: |
|
640 uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); |
|
641 instp += uleblen; |
|
642 len -= uleblen; |
|
643 off += uleblen; |
|
644 printf("\t%2u DW_CFA_restore_extended ", loff); |
|
645 printreg((Dwarf_Signed) uval, config_data); |
|
646 printf("\n"); |
|
647 break; |
|
648 case DW_CFA_undefined: |
|
649 uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); |
|
650 instp += uleblen; |
|
651 len -= uleblen; |
|
652 off += uleblen; |
|
653 printf("\t%2u DW_CFA_undefined ", loff); |
|
654 printreg((Dwarf_Signed) uval, config_data); |
|
655 printf("\n"); |
|
656 break; |
|
657 case DW_CFA_same_value: |
|
658 uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); |
|
659 instp += uleblen; |
|
660 len -= uleblen; |
|
661 off += uleblen; |
|
662 printf("\t%2u DW_CFA_same_value ", loff); |
|
663 printreg((Dwarf_Signed) uval, config_data); |
|
664 printf("\n"); |
|
665 break; |
|
666 case DW_CFA_register: |
|
667 uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); |
|
668 instp += uleblen; |
|
669 len -= uleblen; |
|
670 off += uleblen; |
|
671 uval2 = |
|
672 local_dwarf_decode_u_leb128(instp + 1, &uleblen); |
|
673 instp += uleblen; |
|
674 len -= uleblen; |
|
675 off += uleblen; |
|
676 printf("\t%2u DW_CFA_register ", loff); |
|
677 printreg((Dwarf_Signed) uval, config_data); |
|
678 printf(" = "); |
|
679 printreg((Dwarf_Signed) uval2, config_data); |
|
680 printf("\n"); |
|
681 break; |
|
682 case DW_CFA_remember_state: |
|
683 printf("\t%2u DW_CFA_remember_state\n", loff); |
|
684 break; |
|
685 case DW_CFA_restore_state: |
|
686 printf("\t%2u DW_CFA_restore_state\n", loff); |
|
687 break; |
|
688 case DW_CFA_def_cfa: |
|
689 uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); |
|
690 instp += uleblen; |
|
691 len -= uleblen; |
|
692 off += uleblen; |
|
693 uval2 = |
|
694 local_dwarf_decode_u_leb128(instp + 1, &uleblen); |
|
695 instp += uleblen; |
|
696 len -= uleblen; |
|
697 off += uleblen; |
|
698 printf("\t%2u DW_CFA_def_cfa ", loff); |
|
699 printreg((Dwarf_Signed) uval, config_data); |
|
700 printf(" %llu", (unsigned long long) uval2); |
|
701 printf("\n"); |
|
702 break; |
|
703 case DW_CFA_def_cfa_register: |
|
704 uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); |
|
705 instp += uleblen; |
|
706 len -= uleblen; |
|
707 off += uleblen; |
|
708 printf("\t%2u DW_CFA_def_cfa_register ", loff); |
|
709 printreg((Dwarf_Signed) uval, config_data); |
|
710 printf("\n"); |
|
711 break; |
|
712 case DW_CFA_def_cfa_offset: |
|
713 uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); |
|
714 instp += uleblen; |
|
715 len -= uleblen; |
|
716 off += uleblen; |
|
717 printf("\t%2u DW_CFA_def_cfa_offset %llu\n", |
|
718 loff, (unsigned long long) uval); |
|
719 break; |
|
720 |
|
721 case DW_CFA_nop: |
|
722 printf("\t%2u DW_CFA_nop\n", loff); |
|
723 break; |
|
724 |
|
725 case DW_CFA_def_cfa_expression: /* DWARF3 */ |
|
726 { |
|
727 Dwarf_Unsigned block_len = |
|
728 local_dwarf_decode_u_leb128(instp + 1, |
|
729 &uleblen); |
|
730 |
|
731 instp += uleblen; |
|
732 len -= uleblen; |
|
733 off += uleblen; |
|
734 printf |
|
735 ("\t%2u DW_CFA_def_cfa_expression expr block len %lld\n", |
|
736 loff, (unsigned long long) |
|
737 block_len); |
|
738 dump_block("\t\t", (char *) instp+1, |
|
739 (Dwarf_Signed) block_len); |
|
740 printf("\n"); |
|
741 if(verbose) { |
|
742 struct esb_s exprstring; |
|
743 esb_constructor(&exprstring); |
|
744 get_string_from_locs(dbg, |
|
745 instp+1,block_len,&exprstring); |
|
746 printf("\t\t%s\n",esb_get_string(&exprstring)); |
|
747 esb_destructor(&exprstring); |
|
748 } |
|
749 instp += block_len; |
|
750 len -= block_len; |
|
751 off += block_len; |
|
752 } |
|
753 break; |
|
754 case DW_CFA_expression: /* DWARF3 */ |
|
755 uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); |
|
756 instp += uleblen; |
|
757 len -= uleblen; |
|
758 off += uleblen; |
|
759 { |
|
760 /* instp is always 1 byte back, so we need +1 |
|
761 when we use it. See the final increment |
|
762 of this for loop. */ |
|
763 Dwarf_Unsigned block_len = |
|
764 local_dwarf_decode_u_leb128(instp + 1, |
|
765 &uleblen); |
|
766 |
|
767 instp += uleblen; |
|
768 len -= uleblen; |
|
769 off += uleblen; |
|
770 printf |
|
771 ("\t%2u DW_CFA_expression %llu expr block len %lld\n", |
|
772 loff, (unsigned long long) uval, |
|
773 (unsigned long long) |
|
774 block_len); |
|
775 dump_block("\t\t", (char *) instp+1, |
|
776 (Dwarf_Signed) block_len); |
|
777 printf("\n"); |
|
778 if(verbose) { |
|
779 struct esb_s exprstring; |
|
780 esb_constructor(&exprstring); |
|
781 get_string_from_locs(dbg, |
|
782 instp+1,block_len,&exprstring); |
|
783 printf("\t\t%s\n",esb_get_string(&exprstring)); |
|
784 esb_destructor(&exprstring); |
|
785 } |
|
786 instp += block_len; |
|
787 len -= block_len; |
|
788 off += block_len; |
|
789 } |
|
790 |
|
791 break; |
|
792 case DW_CFA_cfa_offset_extended_sf: /* DWARF3 */ |
|
793 uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); |
|
794 instp += uleblen; |
|
795 len -= uleblen; |
|
796 off += uleblen; |
|
797 { |
|
798 /* instp is always 1 byte back, so we need +1 |
|
799 when we use it. See the final increment |
|
800 of this for loop. */ |
|
801 Dwarf_Signed sval2 = |
|
802 local_dwarf_decode_s_leb128(instp + 1, |
|
803 &uleblen); |
|
804 |
|
805 instp += uleblen; |
|
806 len -= uleblen; |
|
807 off += uleblen; |
|
808 printf("\t%2u DW_CFA_offset_extended_sf ", loff); |
|
809 printreg((Dwarf_Signed) uval, config_data); |
|
810 printf(" %lld", (signed long long) |
|
811 ((sval2) * data_alignment_factor)); |
|
812 if (verbose) { |
|
813 printf(" (%lld * %d)", (long long) sval2, |
|
814 (int) data_alignment_factor); |
|
815 } |
|
816 } |
|
817 printf("\n"); |
|
818 break; |
|
819 case DW_CFA_def_cfa_sf: /* DWARF3 */ |
|
820 /* instp is always 1 byte back, so we need +1 |
|
821 when we use it. See the final increment |
|
822 of this for loop. */ |
|
823 uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); |
|
824 instp += uleblen; |
|
825 len -= uleblen; |
|
826 off += uleblen; |
|
827 { |
|
828 Dwarf_Signed sval2 = |
|
829 local_dwarf_decode_s_leb128(instp + 1, |
|
830 &uleblen); |
|
831 |
|
832 instp += uleblen; |
|
833 len -= uleblen; |
|
834 off += uleblen; |
|
835 printf("\t%2u DW_CFA_def_cfa_sf ", loff); |
|
836 printreg((Dwarf_Signed) uval, config_data); |
|
837 printf(" %lld", (long long) sval2); |
|
838 printf(" (*data alignment factor=>%lld)", |
|
839 (long long)(sval2*data_alignment_factor)); |
|
840 } |
|
841 printf("\n"); |
|
842 break; |
|
843 case DW_CFA_def_cfa_offset_sf: /* DWARF3 */ |
|
844 { |
|
845 /* instp is always 1 byte back, so we need +1 |
|
846 when we use it. See the final increment |
|
847 of this for loop. */ |
|
848 Dwarf_Signed sval = |
|
849 local_dwarf_decode_s_leb128(instp + 1, |
|
850 &uleblen); |
|
851 |
|
852 instp += uleblen; |
|
853 len -= uleblen; |
|
854 off += uleblen; |
|
855 printf("\t%2u DW_CFA_def_cfa_offset_sf %lld (*data alignment factor=> %lld)\n", |
|
856 loff, (long long) sval, |
|
857 (long long)(data_alignment_factor*sval)); |
|
858 |
|
859 } |
|
860 break; |
|
861 case DW_CFA_val_offset: /* DWARF3 */ |
|
862 /* instp is always 1 byte back, so we need +1 |
|
863 when we use it. See the final increment |
|
864 of this for loop. */ |
|
865 uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); |
|
866 instp += uleblen; |
|
867 len -= uleblen; |
|
868 off += uleblen; |
|
869 { |
|
870 uval2 = |
|
871 local_dwarf_decode_s_leb128(instp + 1, |
|
872 &uleblen); |
|
873 instp += uleblen; |
|
874 len -= uleblen; |
|
875 off += uleblen; |
|
876 printf("\t%2u DW_CFA_val_offset ", loff); |
|
877 printreg((Dwarf_Signed) uval, config_data); |
|
878 printf(" %lld", (unsigned long long) |
|
879 (((Dwarf_Signed) uval2) * |
|
880 data_alignment_factor)); |
|
881 if (verbose) { |
|
882 printf(" (%lld * %d)", (long long) uval2, |
|
883 (int) data_alignment_factor); |
|
884 } |
|
885 } |
|
886 printf("\n"); |
|
887 |
|
888 break; |
|
889 case DW_CFA_val_offset_sf: /* DWARF3 */ |
|
890 /* instp is always 1 byte back, so we need +1 |
|
891 when we use it. See the final increment |
|
892 of this for loop. */ |
|
893 uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); |
|
894 instp += uleblen; |
|
895 len -= uleblen; |
|
896 off += uleblen; |
|
897 { |
|
898 Dwarf_Signed sval2 = |
|
899 local_dwarf_decode_s_leb128(instp + 1, |
|
900 &uleblen); |
|
901 |
|
902 instp += uleblen; |
|
903 len -= uleblen; |
|
904 off += uleblen; |
|
905 printf("\t%2u DW_CFA_val_offset_sf ", loff); |
|
906 printreg((Dwarf_Signed) uval, config_data); |
|
907 printf(" %lld", (signed long long) |
|
908 ((sval2) * data_alignment_factor)); |
|
909 if (verbose) { |
|
910 printf(" (%lld * %d)", (long long) sval2, |
|
911 (int) data_alignment_factor); |
|
912 } |
|
913 } |
|
914 printf("\n"); |
|
915 |
|
916 break; |
|
917 case DW_CFA_val_expression: /* DWARF3 */ |
|
918 /* instp is always 1 byte back, so we need +1 |
|
919 when we use it. See the final increment |
|
920 of this for loop. */ |
|
921 uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); |
|
922 instp += uleblen; |
|
923 len -= uleblen; |
|
924 off += uleblen; |
|
925 { |
|
926 Dwarf_Unsigned block_len = |
|
927 local_dwarf_decode_u_leb128(instp + 1, |
|
928 &uleblen); |
|
929 |
|
930 instp += uleblen; |
|
931 len -= uleblen; |
|
932 off += uleblen; |
|
933 printf |
|
934 ("\t%2u DW_CFA_val_expression %llu expr block len %lld\n", |
|
935 loff, (unsigned long long) uval, |
|
936 (unsigned long long) |
|
937 block_len); |
|
938 dump_block("\t\t", (char *) instp+1, |
|
939 (Dwarf_Signed) block_len); |
|
940 printf("\n"); |
|
941 if(verbose) { |
|
942 struct esb_s exprstring; |
|
943 esb_constructor(&exprstring); |
|
944 get_string_from_locs(dbg, |
|
945 instp+1,block_len,&exprstring); |
|
946 printf("\t\t%s\n",esb_get_string(&exprstring)); |
|
947 esb_destructor(&exprstring); |
|
948 } |
|
949 instp += block_len; |
|
950 len -= block_len; |
|
951 off += block_len; |
|
952 } |
|
953 |
|
954 |
|
955 break; |
|
956 |
|
957 |
|
958 #ifdef DW_CFA_GNU_window_save |
|
959 case DW_CFA_GNU_window_save:{ |
|
960 /* no information: this just tells unwinder to |
|
961 restore the window registers from the previous |
|
962 frame's window save area */ |
|
963 printf("\t%2u DW_CFA_GNU_window_save \n", loff); |
|
964 break; |
|
965 } |
|
966 #endif |
|
967 #ifdef DW_CFA_GNU_negative_offset_extended |
|
968 case DW_CFA_GNU_negative_offset_extended:{ |
|
969 printf |
|
970 ("\t%2u DW_CFA_GNU_negative_offset_extended \n", |
|
971 loff); |
|
972 } |
|
973 #endif |
|
974 #ifdef DW_CFA_GNU_args_size |
|
975 /* single uleb128 is the current arg area size in |
|
976 bytes. no register exists yet to save this in */ |
|
977 case DW_CFA_GNU_args_size:{ |
|
978 Dwarf_Unsigned lreg; |
|
979 |
|
980 /* instp is always 1 byte back, so we need +1 |
|
981 when we use it. See the final increment |
|
982 of this for loop. */ |
|
983 lreg = |
|
984 local_dwarf_decode_u_leb128(instp + 1, |
|
985 &uleblen); |
|
986 printf |
|
987 ("\t%2u DW_CFA_GNU_args_size arg size: %llu\n", |
|
988 loff, (unsigned long long) lreg); |
|
989 instp += uleblen; |
|
990 len -= uleblen; |
|
991 off += uleblen; |
|
992 |
|
993 break; |
|
994 } |
|
995 #endif |
|
996 |
|
997 default: |
|
998 printf("\t%u Unexpected op 0x%x: \n", |
|
999 loff, (unsigned int) bottom); |
|
1000 len = 0; |
|
1001 break; |
|
1002 } |
|
1003 } |
|
1004 instp++; |
|
1005 len--; |
|
1006 off++; |
|
1007 } |
|
1008 } |
|
1009 |
|
1010 /* Print our register names for the cases we have a name. |
|
1011 Delegate to the configure code to actually do the print. |
|
1012 */ |
|
1013 void |
|
1014 printreg(Dwarf_Signed reg, struct dwconf_s *config_data) |
|
1015 { |
|
1016 print_reg_from_config_data(reg, config_data); |
|
1017 } |
|
1018 |
|
1019 |
|
1020 /* |
|
1021 Actually does the printing of a rule in the table. |
|
1022 This may print something or may print nothing! |
|
1023 */ |
|
1024 |
|
1025 static void |
|
1026 print_one_frame_reg_col(Dwarf_Debug dbg, |
|
1027 Dwarf_Unsigned rule_id, |
|
1028 Dwarf_Small value_type, |
|
1029 Dwarf_Unsigned reg_used, |
|
1030 struct dwconf_s *config_data, |
|
1031 Dwarf_Signed offset_relevant, |
|
1032 Dwarf_Signed offset, |
|
1033 Dwarf_Ptr block_ptr) |
|
1034 { |
|
1035 char *type_title = ""; |
|
1036 int print_type_title = 1; |
|
1037 |
|
1038 if (config_data->cf_interface_number == 2) |
|
1039 print_type_title = 0; |
|
1040 |
|
1041 switch (value_type) { |
|
1042 case DW_EXPR_OFFSET: |
|
1043 type_title = "off"; |
|
1044 goto preg2; |
|
1045 case DW_EXPR_VAL_OFFSET: |
|
1046 type_title = "valoff"; |
|
1047 preg2: |
|
1048 if (reg_used == config_data->cf_initial_rule_value) { |
|
1049 break; |
|
1050 } |
|
1051 if (print_type_title) |
|
1052 printf("<%s ", type_title); |
|
1053 printreg((Dwarf_Signed) rule_id, config_data); |
|
1054 printf("="); |
|
1055 if (offset_relevant == 0) { |
|
1056 printreg((Dwarf_Signed) reg_used, config_data); |
|
1057 printf(" "); |
|
1058 } else { |
|
1059 printf("%02lld", offset); |
|
1060 printf("("); |
|
1061 printreg((Dwarf_Signed) reg_used, config_data); |
|
1062 printf(") "); |
|
1063 } |
|
1064 if (print_type_title) |
|
1065 printf("%s", "> "); |
|
1066 break; |
|
1067 case DW_EXPR_EXPRESSION: |
|
1068 type_title = "expr"; |
|
1069 goto pexp2; |
|
1070 case DW_EXPR_VAL_EXPRESSION: |
|
1071 type_title = "valexpr"; |
|
1072 pexp2: |
|
1073 if (print_type_title) |
|
1074 printf("<%s ", type_title); |
|
1075 printreg((Dwarf_Signed) rule_id, config_data); |
|
1076 printf("="); |
|
1077 printf("expr-block-len=%lld", (long long) offset); |
|
1078 if (print_type_title) |
|
1079 printf("%s", "> "); |
|
1080 if (verbose) { |
|
1081 char pref[40]; |
|
1082 |
|
1083 strcpy(pref, "<"); |
|
1084 strcat(pref, type_title); |
|
1085 strcat(pref, "bytes:"); |
|
1086 dump_block(pref, block_ptr, offset); |
|
1087 printf("%s", "> "); |
|
1088 if(verbose) { |
|
1089 struct esb_s exprstring; |
|
1090 esb_constructor(&exprstring); |
|
1091 get_string_from_locs(dbg, |
|
1092 block_ptr,offset,&exprstring); |
|
1093 printf("<expr:%s>",esb_get_string(&exprstring)); |
|
1094 esb_destructor(&exprstring); |
|
1095 } |
|
1096 } |
|
1097 break; |
|
1098 default: |
|
1099 printf("Internal error in libdwarf, value type %d\n", |
|
1100 value_type); |
|
1101 exit(1); |
|
1102 } |
|
1103 return; |
|
1104 } |