diff -r 1af5c1be89f8 -r 92d87f2e53c2 tools/elf4rom/libs/dwarf-20071209/dwarfdump/print_frames.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/elf4rom/libs/dwarf-20071209/dwarfdump/print_frames.c Fri Jan 15 09:07:44 2010 +0000 @@ -0,0 +1,1104 @@ +/* + Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2007 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + +$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 $ */ + +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + + + +#include "globals.h" + +#include "print_frames.h" +#include "dwconf.h" +#include "esb.h" + + +static void + print_one_frame_reg_col(Dwarf_Debug dbg, + Dwarf_Unsigned rule_id, + Dwarf_Small value_type, + Dwarf_Unsigned reg_used, + struct dwconf_s *config_data, + Dwarf_Signed offset_relevant, + Dwarf_Signed offset, Dwarf_Ptr block_ptr); + +/* + Gather the fde print logic here so the control logic + determining what FDE to print is clearer. +*/ +int +print_one_fde(Dwarf_Debug dbg, Dwarf_Fde fde, + Dwarf_Unsigned fde_index, + Dwarf_Cie * cie_data, + Dwarf_Signed cie_element_count, + Dwarf_Half address_size, int is_eh, + struct dwconf_s *config_data) +{ + Dwarf_Addr j = 0; + Dwarf_Addr low_pc = 0; + Dwarf_Unsigned func_length = 0; + Dwarf_Ptr fde_bytes = NULL; + Dwarf_Unsigned fde_bytes_length = 0; + Dwarf_Off cie_offset = 0; + Dwarf_Signed cie_index = 0; + Dwarf_Off fde_offset = 0; + Dwarf_Signed eh_table_offset = 0; + int fres = 0; + int offres = 0; + string temps = 0; + Dwarf_Error err = 0; + int printed_intro_addr = 0; + + fres = dwarf_get_fde_range(fde, + &low_pc, &func_length, + &fde_bytes, + &fde_bytes_length, + &cie_offset, &cie_index, + &fde_offset, &err); + if (fres == DW_DLV_ERROR) { + print_error(dbg, "dwarf_get_fde_range", fres, err); + } + if (fres == DW_DLV_NO_ENTRY) { + return DW_DLV_NO_ENTRY; + } + if (cu_name_flag && + fde_offset_for_cu_low != DW_DLV_BADOFFSET && + (fde_offset < fde_offset_for_cu_low || + fde_offset > fde_offset_for_cu_high)) { + return DW_DLV_NO_ENTRY; + } + /* eh_table_offset is IRIX ONLY. */ + fres = dwarf_get_fde_exception_info(fde, &eh_table_offset, &err); + if (fres == DW_DLV_ERROR) { + print_error(dbg, "dwarf_get_fde_exception_info", fres, err); + } + temps = get_fde_proc_name(dbg, low_pc); + printf + ("<%3lld><%#llx:%#llx><%s>", + cie_index, low_pc, (low_pc + func_length), + temps ? temps : "", fde_offset, fde_bytes_length); + + + if (!is_eh) { + /* IRIX uses eh_table_offset. */ + if (eh_table_offset == DW_DLX_NO_EH_OFFSET) { + printf("\n", "none"); + } else if (eh_table_offset == DW_DLX_EH_OFFSET_UNAVAILABLE) { + printf("\n", "unknown"); + } else { + printf("\n", eh_table_offset); + } + } else { + int ares = 0; + Dwarf_Small *data = 0; + Dwarf_Unsigned len = 0; + + ares = dwarf_get_fde_augmentation_data(fde, &data, &len, &err); + if (ares == DW_DLV_NO_ENTRY) { + /* do nothing. */ + } else if (ares == DW_DLV_OK) { + int k2; + + printf(""); + } /* else DW_DLV_ERROR, do nothing */ + printf("\n"); + } + /* call dwarf_get_fde_info_for_reg() to get whole matrix */ + + for (j = low_pc; j < low_pc + func_length; j++) { + Dwarf_Half k; + + if (config_data->cf_interface_number == 3) { + Dwarf_Signed reg = 0; + Dwarf_Signed offset_relevant = 0; + Dwarf_Small value_type = 0; + Dwarf_Signed offset_or_block_len = 0; + Dwarf_Signed offset = 0; + Dwarf_Ptr block_ptr = 0; + Dwarf_Addr row_pc = 0; + + int fires = dwarf_get_fde_info_for_cfa_reg3(fde, + j, + &value_type, + &offset_relevant, + ®, + &offset_or_block_len, + &block_ptr, + &row_pc, + &err); + + offset = offset_or_block_len; + if (fires == DW_DLV_ERROR) { + print_error(dbg, + "dwarf_get_fde_info_for_reg", fires, err); + } + if (fires == DW_DLV_NO_ENTRY) { + continue; + } + if (row_pc != j) { + /* duplicate row */ + continue; + } + if (!printed_intro_addr) { + printf(" %08llx:\t", j); + printed_intro_addr = 1; + } + print_one_frame_reg_col(dbg, config_data->cf_cfa_reg, + value_type, + reg, + config_data, + offset_relevant, offset, block_ptr); + } + for (k = 0; k < config_data->cf_table_entry_count; k++) { + Dwarf_Signed reg = 0; + Dwarf_Signed offset_relevant = 0; + int fires = 0; + Dwarf_Small value_type = 0; + Dwarf_Ptr block_ptr = 0; + Dwarf_Signed offset_or_block_len = 0; + Dwarf_Signed offset = 0; + Dwarf_Addr row_pc = 0; + + if (config_data->cf_interface_number == 3) { + + fires = dwarf_get_fde_info_for_reg3(fde, + k, + j, + &value_type, + &offset_relevant, + ®, + &offset_or_block_len, + &block_ptr, + &row_pc, &err); + offset = offset_or_block_len; + } else { /* ASSERT: + config_data->cf_interface_number == + 2 */ + + + value_type = DW_EXPR_OFFSET; + fires = dwarf_get_fde_info_for_reg(fde, + k, + j, + &offset_relevant, + ®, + &offset, &row_pc, + &err); + } + if (fires == DW_DLV_ERROR) { + printf("\n"); + print_error(dbg, + "dwarf_get_fde_info_for_reg", fires, err); + } + if (fires == DW_DLV_NO_ENTRY) { + continue; + } + if (row_pc != j) { + /* duplicate row */ + break; + } + if (!printed_intro_addr) { + printf(" %08llx:\t", j); + printed_intro_addr = 1; + } + print_one_frame_reg_col(dbg,k, + value_type, + reg, + config_data, + offset_relevant, offset, block_ptr); + + } + if (printed_intro_addr) { + printf("\n"); + printed_intro_addr = 0; + } + } + if (verbose > 1) { + Dwarf_Off fde_off; + Dwarf_Off cie_off; + + /* get the fde instructions and print them in raw form, just + like cie instructions */ + Dwarf_Ptr instrs; + Dwarf_Unsigned ilen; + int res; + + res = dwarf_get_fde_instr_bytes(fde, &instrs, &ilen, &err); + offres = + dwarf_fde_section_offset(dbg, fde, &fde_off, &cie_off, + &err); + if (offres == DW_DLV_OK) { + printf("\tfde sec. offset %llu 0x%llx" + " cie offset for fde: %llu 0x%llx\n", + (unsigned long long) fde_off, + (unsigned long long) fde_off, + (unsigned long long) cie_off, + (unsigned long long) cie_off); + + } + + + if (res == DW_DLV_OK) { + int cires = 0; + Dwarf_Unsigned cie_length = 0; + Dwarf_Small version = 0; + string augmenter; + Dwarf_Unsigned code_alignment_factor = 0; + Dwarf_Signed data_alignment_factor = 0; + Dwarf_Half return_address_register_rule = 0; + Dwarf_Ptr initial_instructions = 0; + Dwarf_Unsigned initial_instructions_length = 0; + + if (cie_index >= cie_element_count) { + printf("Bad cie index %lld with fde index %lld! " + "(table entry max %lld)\n", + (long long) cie_index, (long long) fde_index, + (long long) cie_element_count); + exit(1); + } + + cires = dwarf_get_cie_info(cie_data[cie_index], + &cie_length, + &version, + &augmenter, + &code_alignment_factor, + &data_alignment_factor, + &return_address_register_rule, + &initial_instructions, + &initial_instructions_length, + &err); + if (cires == DW_DLV_ERROR) { + printf + ("Bad cie index %lld with fde index %lld!\n", + (long long) cie_index, (long long) fde_index); + print_error(dbg, "dwarf_get_cie_info", cires, err); + } + if (cires == DW_DLV_NO_ENTRY) { + ; /* ? */ + } else { + + print_frame_inst_bytes(dbg, instrs, + (Dwarf_Signed) ilen, + data_alignment_factor, + (int) code_alignment_factor, + address_size, config_data); + } + } else if (res == DW_DLV_NO_ENTRY) { + printf + ("Impossible: no instr bytes for fde index %d?\n", + (int) fde_index); + } else { + /* DW_DLV_ERROR */ + printf + ("Error: on gettinginstr bytes for fde index %d?\n", + (int) fde_index); + print_error(dbg, "dwarf_get_fde_instr_bytes", res, err); + } + + } + return DW_DLV_OK; +} + + +/* Print a cie. Gather the print logic here so the + control logic deciding what to print + is clearer. +*/ +int +print_one_cie(Dwarf_Debug dbg, Dwarf_Cie cie, + Dwarf_Unsigned cie_index, Dwarf_Half address_size, + struct dwconf_s *config_data) +{ + + int cires = 0; + Dwarf_Unsigned cie_length = 0; + Dwarf_Small version = 0; + string augmenter = ""; + Dwarf_Unsigned code_alignment_factor = 0; + Dwarf_Signed data_alignment_factor = 0; + Dwarf_Half return_address_register_rule = 0; + Dwarf_Ptr initial_instructions = 0; + Dwarf_Unsigned initial_instructions_length = 0; + Dwarf_Off cie_off = 0; + Dwarf_Error err = 0; + + cires = dwarf_get_cie_info(cie, + &cie_length, + &version, + &augmenter, + &code_alignment_factor, + &data_alignment_factor, + &return_address_register_rule, + &initial_instructions, + &initial_instructions_length, &err); + if (cires == DW_DLV_ERROR) { + print_error(dbg, "dwarf_get_cie_info", cires, err); + } + if (cires == DW_DLV_NO_ENTRY) { + ; /* ? */ + printf("Impossible DW_DLV_NO_ENTRY on cie %d\n", + (int) cie_index); + return DW_DLV_NO_ENTRY; + } + { + printf("<%3lld>\tversion\t\t\t\t%d\n", cie_index, version); + cires = dwarf_cie_section_offset(dbg, cie, &cie_off, &err); + if (cires == DW_DLV_OK) { + printf("\tcie sec. offset %llu 0x%llx\n", + (unsigned long long) cie_off, + (unsigned long long) cie_off); + + } + + printf("\taugmentation\t\t\t%s\n", augmenter); + printf("\tcode_alignment_factor\t\t%llu\n", + (unsigned long long) code_alignment_factor); + printf("\tdata_alignment_factor\t\t%lld\n", + (long long) data_alignment_factor); + printf("\treturn_address_register\t\t%d\n", + (int) return_address_register_rule); + { + int ares = 0; + Dwarf_Small *data = 0; + Dwarf_Unsigned len = 0; + + ares = + dwarf_get_cie_augmentation_data(cie, &data, &len, &err); + if (ares == DW_DLV_NO_ENTRY) { + /* do nothing. */ + } else if (ares == DW_DLV_OK && len > 0) { + int k2; + + printf("\teh aug data len 0x%llx", (long long) len); + for (k2 = 0; data && k2 < len; ++k2) { + if (k2 == 0) { + printf(" bytes 0x"); + } + printf("%02x ", (unsigned char) data[k2]); + } + printf("\n"); + } /* else DW_DLV_ERROR or no data, do + nothing */ + } + + printf + ("\tbytes of initial instructions:\t%lld\n", + (long long) initial_instructions_length); + printf("\tcie length :\t\t\t%lld\n", (long long) cie_length); + print_frame_inst_bytes(dbg, initial_instructions, (Dwarf_Signed) + initial_instructions_length, + data_alignment_factor, + (int) code_alignment_factor, + address_size, config_data); + } + return DW_DLV_OK; +} + +void +get_string_from_locs(Dwarf_Debug dbg, + Dwarf_Ptr bytes_in, + Dwarf_Unsigned block_len,struct esb_s *out_string) +{ + + Dwarf_Locdesc *locdescarray = 0; + Dwarf_Signed listlen = 0; + Dwarf_Error err2 =0; + int skip_locdesc_header=1; + int res2 = dwarf_loclist_from_expr(dbg, + bytes_in,block_len, + &locdescarray, + &listlen,&err2); + if (res2 == DW_DLV_ERROR) { + print_error(dbg, "dwarf_get_loclist_from_expr", + res2, err2); + } + if(res2==DW_DLV_NO_ENTRY) { + return; + } + /* lcnt is always 1 */ + + /* Use locdescarray here.*/ + int res = dwarfdump_print_one_locdesc(dbg, + locdescarray, + skip_locdesc_header, + out_string); + if(res != DW_DLV_OK) { + printf("Bad status from _dwarf_print_one_locdesc %d\n",res); + exit(1); + } + + + + dwarf_dealloc(dbg, locdescarray->ld_s, DW_DLA_LOC_BLOCK); + dwarf_dealloc(dbg, locdescarray, DW_DLA_LOCDESC); + + + return ; +} + +/* Print the frame instructions in detail for a glob of instructions. +*/ + + /*ARGSUSED*/ void +print_frame_inst_bytes(Dwarf_Debug dbg, + Dwarf_Ptr cie_init_inst, Dwarf_Signed len, + Dwarf_Signed data_alignment_factor, + int code_alignment_factor, Dwarf_Half addr_size, + struct dwconf_s *config_data) +{ + unsigned char *instp = (unsigned char *) cie_init_inst; + Dwarf_Unsigned uval; + Dwarf_Unsigned uval2; + unsigned int uleblen; + unsigned int off = 0; + unsigned int loff = 0; + unsigned short u16; + unsigned int u32; + unsigned long long u64; + + for (; len > 0;) { + unsigned char ibyte = *instp; + int top = ibyte & 0xc0; + int bottom = ibyte & 0x3f; + int delta; + int reg; + + switch (top) { + case DW_CFA_advance_loc: + delta = ibyte & 0x3f; + printf("\t%2u DW_CFA_advance_loc %d", off, + (int) (delta * code_alignment_factor)); + if (verbose) { + printf(" (%d * %d)", (int) delta, + (int) code_alignment_factor); + } + printf("\n"); + break; + case DW_CFA_offset: + loff = off; + reg = ibyte & 0x3f; + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_offset ", loff); + printreg((Dwarf_Signed) reg, config_data); + printf(" %lld", (signed long long) + (((Dwarf_Signed) uval) * data_alignment_factor)); + if (verbose) { + printf(" (%llu * %d)", (unsigned long long) uval, + (int) data_alignment_factor); + } + printf("\n"); + break; + + case DW_CFA_restore: + reg = ibyte & 0x3f; + printf("\t%2u DW_CFA_restore \n", off); + printreg((Dwarf_Signed) reg, config_data); + printf("\n"); + break; + + default: + loff = off; + switch (bottom) { + case DW_CFA_set_loc: + /* operand is address, so need address size */ + /* which will be 4 or 8. */ + switch (addr_size) { + case 4: + { + __uint32_t v32; + + memcpy(&v32, instp + 1, addr_size); + uval = v32; + } + break; + case 8: + { + __uint64_t v64; + + memcpy(&v64, instp + 1, addr_size); + uval = v64; + } + break; + default: + printf + ("Error: Unexpected address size %d in DW_CFA_set_loc!\n", + addr_size); + uval = 0; + } + + instp += addr_size; + len -= (Dwarf_Signed) addr_size; + off += addr_size; + printf("\t%2u DW_CFA_set_loc %llu\n", + loff, (unsigned long long) uval); + break; + case DW_CFA_advance_loc1: + delta = (unsigned char) *(instp + 1); + uval2 = delta; + instp += 1; + len -= 1; + off += 1; + printf("\t%2u DW_CFA_advance_loc1 %llu\n", + loff, (unsigned long long) uval2); + break; + case DW_CFA_advance_loc2: + memcpy(&u16, instp + 1, 2); + uval2 = u16; + instp += 2; + len -= 2; + off += 2; + printf("\t%2u DW_CFA_advance_loc2 %llu\n", + loff, (unsigned long long) uval2); + break; + case DW_CFA_advance_loc4: + memcpy(&u32, instp + 1, 4); + uval2 = u32; + instp += 4; + len -= 4; + off += 4; + printf("\t%2u DW_CFA_advance_loc4 %llu\n", + loff, (unsigned long long) uval2); + break; + case DW_CFA_MIPS_advance_loc8: + memcpy(&u64, instp + 1, 8); + uval2 = u64; + instp += 8; + len -= 8; + off += 8; + printf("\t%2u DW_CFA_MIPS_advance_loc8 %llu\n", + loff, (unsigned long long) uval2); + break; + case DW_CFA_offset_extended: + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + uval2 = + local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_offset_extended ", loff); + printreg((Dwarf_Signed) uval, config_data); + printf(" %lld", (signed long long) + (((Dwarf_Signed) uval2) * + data_alignment_factor)); + if (verbose) { + printf(" (%llu * %d)", (unsigned long long) uval2, + (int) data_alignment_factor); + } + printf("\n"); + break; + + case DW_CFA_restore_extended: + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_restore_extended ", loff); + printreg((Dwarf_Signed) uval, config_data); + printf("\n"); + break; + case DW_CFA_undefined: + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_undefined ", loff); + printreg((Dwarf_Signed) uval, config_data); + printf("\n"); + break; + case DW_CFA_same_value: + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_same_value ", loff); + printreg((Dwarf_Signed) uval, config_data); + printf("\n"); + break; + case DW_CFA_register: + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + uval2 = + local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_register ", loff); + printreg((Dwarf_Signed) uval, config_data); + printf(" = "); + printreg((Dwarf_Signed) uval2, config_data); + printf("\n"); + break; + case DW_CFA_remember_state: + printf("\t%2u DW_CFA_remember_state\n", loff); + break; + case DW_CFA_restore_state: + printf("\t%2u DW_CFA_restore_state\n", loff); + break; + case DW_CFA_def_cfa: + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + uval2 = + local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_def_cfa ", loff); + printreg((Dwarf_Signed) uval, config_data); + printf(" %llu", (unsigned long long) uval2); + printf("\n"); + break; + case DW_CFA_def_cfa_register: + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_def_cfa_register ", loff); + printreg((Dwarf_Signed) uval, config_data); + printf("\n"); + break; + case DW_CFA_def_cfa_offset: + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_def_cfa_offset %llu\n", + loff, (unsigned long long) uval); + break; + + case DW_CFA_nop: + printf("\t%2u DW_CFA_nop\n", loff); + break; + + case DW_CFA_def_cfa_expression: /* DWARF3 */ + { + Dwarf_Unsigned block_len = + local_dwarf_decode_u_leb128(instp + 1, + &uleblen); + + instp += uleblen; + len -= uleblen; + off += uleblen; + printf + ("\t%2u DW_CFA_def_cfa_expression expr block len %lld\n", + loff, (unsigned long long) + block_len); + dump_block("\t\t", (char *) instp+1, + (Dwarf_Signed) block_len); + printf("\n"); + if(verbose) { + struct esb_s exprstring; + esb_constructor(&exprstring); + get_string_from_locs(dbg, + instp+1,block_len,&exprstring); + printf("\t\t%s\n",esb_get_string(&exprstring)); + esb_destructor(&exprstring); + } + instp += block_len; + len -= block_len; + off += block_len; + } + break; + case DW_CFA_expression: /* DWARF3 */ + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + { + /* instp is always 1 byte back, so we need +1 + when we use it. See the final increment + of this for loop. */ + Dwarf_Unsigned block_len = + local_dwarf_decode_u_leb128(instp + 1, + &uleblen); + + instp += uleblen; + len -= uleblen; + off += uleblen; + printf + ("\t%2u DW_CFA_expression %llu expr block len %lld\n", + loff, (unsigned long long) uval, + (unsigned long long) + block_len); + dump_block("\t\t", (char *) instp+1, + (Dwarf_Signed) block_len); + printf("\n"); + if(verbose) { + struct esb_s exprstring; + esb_constructor(&exprstring); + get_string_from_locs(dbg, + instp+1,block_len,&exprstring); + printf("\t\t%s\n",esb_get_string(&exprstring)); + esb_destructor(&exprstring); + } + instp += block_len; + len -= block_len; + off += block_len; + } + + break; + case DW_CFA_cfa_offset_extended_sf: /* DWARF3 */ + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + { + /* instp is always 1 byte back, so we need +1 + when we use it. See the final increment + of this for loop. */ + Dwarf_Signed sval2 = + local_dwarf_decode_s_leb128(instp + 1, + &uleblen); + + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_offset_extended_sf ", loff); + printreg((Dwarf_Signed) uval, config_data); + printf(" %lld", (signed long long) + ((sval2) * data_alignment_factor)); + if (verbose) { + printf(" (%lld * %d)", (long long) sval2, + (int) data_alignment_factor); + } + } + printf("\n"); + break; + case DW_CFA_def_cfa_sf: /* DWARF3 */ + /* instp is always 1 byte back, so we need +1 + when we use it. See the final increment + of this for loop. */ + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + { + Dwarf_Signed sval2 = + local_dwarf_decode_s_leb128(instp + 1, + &uleblen); + + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_def_cfa_sf ", loff); + printreg((Dwarf_Signed) uval, config_data); + printf(" %lld", (long long) sval2); + printf(" (*data alignment factor=>%lld)", + (long long)(sval2*data_alignment_factor)); + } + printf("\n"); + break; + case DW_CFA_def_cfa_offset_sf: /* DWARF3 */ + { + /* instp is always 1 byte back, so we need +1 + when we use it. See the final increment + of this for loop. */ + Dwarf_Signed sval = + local_dwarf_decode_s_leb128(instp + 1, + &uleblen); + + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_def_cfa_offset_sf %lld (*data alignment factor=> %lld)\n", + loff, (long long) sval, + (long long)(data_alignment_factor*sval)); + + } + break; + case DW_CFA_val_offset: /* DWARF3 */ + /* instp is always 1 byte back, so we need +1 + when we use it. See the final increment + of this for loop. */ + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + { + uval2 = + local_dwarf_decode_s_leb128(instp + 1, + &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_val_offset ", loff); + printreg((Dwarf_Signed) uval, config_data); + printf(" %lld", (unsigned long long) + (((Dwarf_Signed) uval2) * + data_alignment_factor)); + if (verbose) { + printf(" (%lld * %d)", (long long) uval2, + (int) data_alignment_factor); + } + } + printf("\n"); + + break; + case DW_CFA_val_offset_sf: /* DWARF3 */ + /* instp is always 1 byte back, so we need +1 + when we use it. See the final increment + of this for loop. */ + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + { + Dwarf_Signed sval2 = + local_dwarf_decode_s_leb128(instp + 1, + &uleblen); + + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_val_offset_sf ", loff); + printreg((Dwarf_Signed) uval, config_data); + printf(" %lld", (signed long long) + ((sval2) * data_alignment_factor)); + if (verbose) { + printf(" (%lld * %d)", (long long) sval2, + (int) data_alignment_factor); + } + } + printf("\n"); + + break; + case DW_CFA_val_expression: /* DWARF3 */ + /* instp is always 1 byte back, so we need +1 + when we use it. See the final increment + of this for loop. */ + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + { + Dwarf_Unsigned block_len = + local_dwarf_decode_u_leb128(instp + 1, + &uleblen); + + instp += uleblen; + len -= uleblen; + off += uleblen; + printf + ("\t%2u DW_CFA_val_expression %llu expr block len %lld\n", + loff, (unsigned long long) uval, + (unsigned long long) + block_len); + dump_block("\t\t", (char *) instp+1, + (Dwarf_Signed) block_len); + printf("\n"); + if(verbose) { + struct esb_s exprstring; + esb_constructor(&exprstring); + get_string_from_locs(dbg, + instp+1,block_len,&exprstring); + printf("\t\t%s\n",esb_get_string(&exprstring)); + esb_destructor(&exprstring); + } + instp += block_len; + len -= block_len; + off += block_len; + } + + + break; + + +#ifdef DW_CFA_GNU_window_save + case DW_CFA_GNU_window_save:{ + /* no information: this just tells unwinder to + restore the window registers from the previous + frame's window save area */ + printf("\t%2u DW_CFA_GNU_window_save \n", loff); + break; + } +#endif +#ifdef DW_CFA_GNU_negative_offset_extended + case DW_CFA_GNU_negative_offset_extended:{ + printf + ("\t%2u DW_CFA_GNU_negative_offset_extended \n", + loff); + } +#endif +#ifdef DW_CFA_GNU_args_size + /* single uleb128 is the current arg area size in + bytes. no register exists yet to save this in */ + case DW_CFA_GNU_args_size:{ + Dwarf_Unsigned lreg; + + /* instp is always 1 byte back, so we need +1 + when we use it. See the final increment + of this for loop. */ + lreg = + local_dwarf_decode_u_leb128(instp + 1, + &uleblen); + printf + ("\t%2u DW_CFA_GNU_args_size arg size: %llu\n", + loff, (unsigned long long) lreg); + instp += uleblen; + len -= uleblen; + off += uleblen; + + break; + } +#endif + + default: + printf("\t%u Unexpected op 0x%x: \n", + loff, (unsigned int) bottom); + len = 0; + break; + } + } + instp++; + len--; + off++; + } +} + +/* Print our register names for the cases we have a name. + Delegate to the configure code to actually do the print. +*/ +void +printreg(Dwarf_Signed reg, struct dwconf_s *config_data) +{ + print_reg_from_config_data(reg, config_data); +} + + +/* + Actually does the printing of a rule in the table. + This may print something or may print nothing! +*/ + +static void +print_one_frame_reg_col(Dwarf_Debug dbg, + Dwarf_Unsigned rule_id, + Dwarf_Small value_type, + Dwarf_Unsigned reg_used, + struct dwconf_s *config_data, + Dwarf_Signed offset_relevant, + Dwarf_Signed offset, + Dwarf_Ptr block_ptr) +{ + char *type_title = ""; + int print_type_title = 1; + + if (config_data->cf_interface_number == 2) + print_type_title = 0; + + switch (value_type) { + case DW_EXPR_OFFSET: + type_title = "off"; + goto preg2; + case DW_EXPR_VAL_OFFSET: + type_title = "valoff"; + preg2: + if (reg_used == config_data->cf_initial_rule_value) { + break; + } + if (print_type_title) + printf("<%s ", type_title); + printreg((Dwarf_Signed) rule_id, config_data); + printf("="); + if (offset_relevant == 0) { + printreg((Dwarf_Signed) reg_used, config_data); + printf(" "); + } else { + printf("%02lld", offset); + printf("("); + printreg((Dwarf_Signed) reg_used, config_data); + printf(") "); + } + if (print_type_title) + printf("%s", "> "); + break; + case DW_EXPR_EXPRESSION: + type_title = "expr"; + goto pexp2; + case DW_EXPR_VAL_EXPRESSION: + type_title = "valexpr"; + pexp2: + if (print_type_title) + printf("<%s ", type_title); + printreg((Dwarf_Signed) rule_id, config_data); + printf("="); + printf("expr-block-len=%lld", (long long) offset); + if (print_type_title) + printf("%s", "> "); + if (verbose) { + char pref[40]; + + strcpy(pref, "<"); + strcat(pref, type_title); + strcat(pref, "bytes:"); + dump_block(pref, block_ptr, offset); + printf("%s", "> "); + if(verbose) { + struct esb_s exprstring; + esb_constructor(&exprstring); + get_string_from_locs(dbg, + block_ptr,offset,&exprstring); + printf("",esb_get_string(&exprstring)); + esb_destructor(&exprstring); + } + } + break; + default: + printf("Internal error in libdwarf, value type %d\n", + value_type); + exit(1); + } + return; +}