tools/elf4rom/libs/dwarf-20071209/dwarfdump/print_frames.c
changeset 34 92d87f2e53c2
--- /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><fde offset 0x%llx length: 0x%llx>",
+	 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("<eh offset %s>\n", "none");
+	} else if (eh_table_offset == DW_DLX_EH_OFFSET_UNAVAILABLE) {
+	    printf("<eh offset %s>\n", "unknown");
+	} else {
+	    printf("<eh offset 0x%llx>\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("<eh aug data len 0x%llx", (long long) len);
+	    for (k2 = 0; k2 < len; ++k2) {
+		if (k2 == 0) {
+		    printf(" bytes 0x");
+		}
+		printf("%02x ", (unsigned char) data[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,
+							&reg,
+							&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,
+						    &reg,
+						    &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,
+						   &reg,
+						   &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("<expr:%s>",esb_get_string(&exprstring));
+                      esb_destructor(&exprstring);
+            }
+	}
+	break;
+    default:
+	printf("Internal error in libdwarf, value type %d\n",
+	       value_type);
+	exit(1);
+    }
+    return;
+}